Merge "Prevent sign extension in IccUtils.parseToRGB"
diff --git a/api/current.xml b/api/current.xml
index 00f7505..5e483956 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -4611,7 +4611,7 @@
type="int"
transient="false"
volatile="false"
- value="16843448"
+ value="16843447"
static="true"
final="true"
deprecated="not deprecated"
@@ -5773,17 +5773,6 @@
visibility="public"
>
</field>
-<field name="neverEncrypt"
- type="int"
- transient="false"
- volatile="false"
- value="16843447"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="nextFocusDown"
type="int"
transient="false"
@@ -6855,7 +6844,7 @@
type="int"
transient="false"
volatile="false"
- value="16843449"
+ value="16843448"
static="true"
final="true"
deprecated="not deprecated"
@@ -9073,6 +9062,17 @@
visibility="public"
>
</field>
+<field name="webTextViewStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843449"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="webViewStyle"
type="int"
transient="false"
@@ -20056,242 +20056,6 @@
</parameter>
</method>
</interface>
-<class name="DeviceAdmin"
- extends="android.content.BroadcastReceiver"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="DeviceAdmin"
- type="android.app.DeviceAdmin"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="getManager"
- return="android.app.DevicePolicyManager"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-</method>
-<method name="getWho"
- return="android.content.ComponentName"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-</method>
-<method name="onDisableRequested"
- return="java.lang.CharSequence"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-</method>
-<method name="onDisabled"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-</method>
-<method name="onEnabled"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-</method>
-<method name="onPasswordChanged"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-</method>
-<method name="onPasswordFailed"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-</method>
-<method name="onPasswordSucceeded"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-</method>
-<method name="onReceive"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-</method>
-<field name="ACTION_DEVICE_ADMIN_DISABLED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.app.action.DEVICE_ADMIN_DISABLED""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_DEVICE_ADMIN_DISABLE_REQUESTED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_DEVICE_ADMIN_ENABLED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.app.action.DEVICE_ADMIN_ENABLED""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_PASSWORD_CHANGED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.app.action.ACTION_PASSWORD_CHANGED""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_PASSWORD_FAILED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.app.action.ACTION_PASSWORD_FAILED""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_PASSWORD_SUCCEEDED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.app.action.ACTION_PASSWORD_SUCCEEDED""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="DEVICE_ADMIN_META_DATA"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.app.device_admin""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EXTRA_DISABLE_WARNING"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.app.extra.DISABLE_WARNING""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
<class name="DeviceAdminInfo"
extends="java.lang.Object"
abstract="false"
@@ -20536,6 +20300,242 @@
>
</field>
</class>
+<class name="DeviceAdminReceiver"
+ extends="android.content.BroadcastReceiver"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DeviceAdminReceiver"
+ type="android.app.DeviceAdminReceiver"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getManager"
+ return="android.app.DevicePolicyManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="getWho"
+ return="android.content.ComponentName"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="onDisableRequested"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onDisabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onPasswordChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onPasswordFailed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onPasswordSucceeded"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onReceive"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<field name="ACTION_DEVICE_ADMIN_DISABLED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.app.action.DEVICE_ADMIN_DISABLED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DEVICE_ADMIN_DISABLE_REQUESTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DEVICE_ADMIN_ENABLED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.app.action.DEVICE_ADMIN_ENABLED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_PASSWORD_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.app.action.ACTION_PASSWORD_CHANGED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_PASSWORD_FAILED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.app.action.ACTION_PASSWORD_FAILED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_PASSWORD_SUCCEEDED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.app.action.ACTION_PASSWORD_SUCCEEDED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DEVICE_ADMIN_META_DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.app.device_admin""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DISABLE_WARNING"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.app.extra.DISABLE_WARNING""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="DevicePolicyManager"
extends="java.lang.Object"
abstract="false"
@@ -150327,9 +150327,9 @@
</parameter>
<parameter name="align" type="android.text.Layout.Alignment">
</parameter>
-<parameter name="spacingmult" type="float">
+<parameter name="spacingMult" type="float">
</parameter>
-<parameter name="spacingadd" type="float">
+<parameter name="spacingAdd" type="float">
</parameter>
</constructor>
<method name="draw"
@@ -150359,7 +150359,7 @@
</parameter>
<parameter name="highlight" type="android.graphics.Path">
</parameter>
-<parameter name="highlightpaint" type="android.graphics.Paint">
+<parameter name="highlightPaint" type="android.graphics.Paint">
</parameter>
<parameter name="cursorOffsetVertical" type="int">
</parameter>
diff --git a/core/java/android/app/DeviceAdminInfo.java b/core/java/android/app/DeviceAdminInfo.java
index 159fa75..bedf4b4 100644
--- a/core/java/android/app/DeviceAdminInfo.java
+++ b/core/java/android/app/DeviceAdminInfo.java
@@ -60,8 +60,8 @@
/**
* A type of policy that this device admin can use: able to watch login
- * attempts from the user, via {@link DeviceAdmin#ACTION_PASSWORD_FAILED},
- * {@link DeviceAdmin#ACTION_PASSWORD_SUCCEEDED}, and
+ * attempts from the user, via {@link DeviceAdminReceiver#ACTION_PASSWORD_FAILED},
+ * {@link DeviceAdminReceiver#ACTION_PASSWORD_SUCCEEDED}, and
* {@link DevicePolicyManager#getCurrentFailedPasswordAttempts}.
*
* <p>To control this policy, the device admin must have a "watch-login"
@@ -169,10 +169,10 @@
XmlResourceParser parser = null;
try {
- parser = ai.loadXmlMetaData(pm, DeviceAdmin.DEVICE_ADMIN_META_DATA);
+ parser = ai.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA);
if (parser == null) {
throw new XmlPullParserException("No "
- + DeviceAdmin.DEVICE_ADMIN_META_DATA + " meta-data");
+ + DeviceAdminReceiver.DEVICE_ADMIN_META_DATA + " meta-data");
}
AttributeSet attrs = Xml.asAttributeSet(parser);
diff --git a/core/java/android/app/DeviceAdmin.java b/core/java/android/app/DeviceAdminReceiver.java
similarity index 93%
rename from core/java/android/app/DeviceAdmin.java
rename to core/java/android/app/DeviceAdminReceiver.java
index af9c379..453e0bf 100644
--- a/core/java/android/app/DeviceAdmin.java
+++ b/core/java/android/app/DeviceAdminReceiver.java
@@ -29,6 +29,13 @@
* class provides a convenience for interpreting the raw intent actions
* that are sent by the system.
*
+ * <p>The callback methods, like the base
+ * {@link BroadcastReceiver#onReceive(Context, Intent) BroadcastReceiver.onReceive()}
+ * method, happen on the main thread of the process. Thus long running
+ * operations must be done on another thread. Note that because a receiver
+ * is done once returning from its receive function, such long-running operations
+ * should probably be done in a {@link Service}.
+ *
* <p>When publishing your DeviceAdmin subclass as a receiver, it must
* handle {@link #ACTION_DEVICE_ADMIN_ENABLED} and require the
* {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission. A typical
@@ -42,7 +49,7 @@
*
* {@sample development/samples/ApiDemos/res/xml/device_admin_sample.xml meta_data}
*/
-public class DeviceAdmin extends BroadcastReceiver {
+public class DeviceAdminReceiver extends BroadcastReceiver {
private static String TAG = "DevicePolicy";
private static boolean DEBUG = false;
private static boolean localLOGV = DEBUG || android.util.Config.LOGV;
@@ -51,7 +58,7 @@
* This is the primary action that a device administrator must implement to be
* allowed to manage a device. This will be set to the receiver
* when the user enables it for administration. You will generally
- * handle this in {@link DeviceAdmin#onEnabled(Context, Intent)}. To be
+ * handle this in {@link DeviceAdminReceiver#onEnabled(Context, Intent)}. To be
* supported, the receiver must also require the
* {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission so
* that other applications can not abuse it.
@@ -85,7 +92,7 @@
* Action sent to a device administrator when the user has disabled
* it. Upon return, the application no longer has access to the
* protected device policy manager APIs. You will generally
- * handle this in {@link DeviceAdmin#onDisabled(Context, Intent)}. Note
+ * handle this in {@link DeviceAdminReceiver#onDisabled(Context, Intent)}. Note
* that this action will be
* sent the receiver regardless of whether it is explicitly listed in
* its intent filter.
@@ -100,7 +107,7 @@
* of the new password with {@link DevicePolicyManager#isActivePasswordSufficient()
* DevicePolicyManager.isActivePasswordSufficient()}.
* You will generally
- * handle this in {@link DeviceAdmin#onPasswordChanged}.
+ * handle this in {@link DeviceAdminReceiver#onPasswordChanged}.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive
@@ -116,7 +123,7 @@
* number of failed password attempts there have been with
* {@link DevicePolicyManager#getCurrentFailedPasswordAttempts
* DevicePolicyManager.getCurrentFailedPasswordAttempts()}. You will generally
- * handle this in {@link DeviceAdmin#onPasswordFailed}.
+ * handle this in {@link DeviceAdminReceiver#onPasswordFailed}.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java
index 82c43dc..d611807 100644
--- a/core/java/android/app/DevicePolicyManager.java
+++ b/core/java/android/app/DevicePolicyManager.java
@@ -36,7 +36,7 @@
/**
* Public interface for managing policies enforced on a device. Most clients
- * of this class must have published a {@link DeviceAdmin} that the user
+ * of this class must have published a {@link DeviceAdminReceiver} that the user
* has currently enabled.
*/
public class DevicePolicyManager {
@@ -195,7 +195,7 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
- * @param admin Which {@link DeviceAdmin} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param quality The new desired quality. One of
* {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING},
* {@link #PASSWORD_QUALITY_NUMERIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC}.
@@ -243,7 +243,7 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
- * @param admin Which {@link DeviceAdmin} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param length The new desired minimum password length. A value of 0
* means there is no restriction.
*/
@@ -338,11 +338,11 @@
* <p>To implement any other policy (e.g. wiping data for a particular
* application only, erasing or revoking credentials, or reporting the
* failure to a server), you should implement
- * {@link DeviceAdmin#onPasswordFailed(Context, android.content.Intent)}
+ * {@link DeviceAdminReceiver#onPasswordFailed(Context, android.content.Intent)}
* instead. Do not use this API, because if the maximum count is reached,
* the device will be wiped immediately, and your callback will not be invoked.
*
- * @param admin Which {@link DeviceAdmin} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param num The number of failed password attempts at which point the
* device will wipe its data.
*/
@@ -375,7 +375,9 @@
}
/**
- * Force a new password on the user. This takes effect immediately.
+ * Force a new device unlock password (the password needed to access the
+ * entire device, not for individual accounts) on the user. This takes
+ * effect immediately.
* The given password must be sufficient for the
* current password quality and length constraints as returned by
* {@link #getPasswordQuality(ComponentName)} and
@@ -413,7 +415,7 @@
* {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
* this method; if it has not, a security exception will be thrown.
*
- * @param admin Which {@link DeviceAdmin} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param timeMs The new desired maximum time to lock in milliseconds.
* A value of 0 means there is no restriction.
*/
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 544e399..acb8473 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -608,6 +608,45 @@
}
/**
+ * URI parameter and cursor extras that return counts of rows grouped by the
+ * address book index, which is usually the first letter of the sort key.
+ * When this parameter is supplied, the row counts are returned in the
+ * cursor extras bundle.
+ *
+ * @hide
+ */
+ public final static class ContactCounts {
+
+ /**
+ * Add this query parameter to a URI to get back row counts grouped by
+ * the address book index as cursor extras. For most languages it is the
+ * first letter of the sort key. This parameter does not affect the main
+ * content of the cursor.
+ *
+ * @hide
+ */
+ public static final String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
+
+ /**
+ * The array of address book index titles, which are returned in the
+ * same order as the data in the cursor.
+ * <p>TYPE: String[]</p>
+ *
+ * @hide
+ */
+ public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+
+ /**
+ * The array of group counts for the corresponding group. Contains the same number
+ * of elements as the EXTRA_ADDRESS_BOOK_INDEX_TITLES array.
+ * <p>TYPE: int[]</p>
+ *
+ * @hide
+ */
+ public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
+ }
+
+ /**
* Constants for the contacts table, which contains a record per aggregate
* of raw contacts representing the same person.
* <h3>Operations</h3>
@@ -5695,5 +5734,4 @@
public static final String IM_ISPRIMARY = "im_isprimary";
}
}
-
}
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 22bb43c..096ad39 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -121,10 +121,44 @@
handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED);
}
}
+ } else if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
+ int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ if (streamType == AudioManager.STREAM_MUSIC) {
+ BluetoothDevice sinks[] = getConnectedSinks();
+ if (sinks.length != 0 && isPhoneDocked(sinks[0])) {
+ String address = sinks[0].getAddress();
+ int newVolLevel =
+ intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
+ int oldVolLevel =
+ intent.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
+ String path = mBluetoothService.getObjectPathFromAddress(address);
+ if (newVolLevel > oldVolLevel) {
+ avrcpVolumeUpNative(path);
+ } else if (newVolLevel < oldVolLevel) {
+ avrcpVolumeDownNative(path);
+ }
+ }
+ }
}
}
};
+
+ private boolean isPhoneDocked(BluetoothDevice device) {
+ // This works only because these broadcast intents are "sticky"
+ Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
+ if (i != null) {
+ int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+ BluetoothDevice dockDevice = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if (dockDevice != null && device.equals(dockDevice)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public BluetoothA2dpService(Context context, BluetoothService bluetoothService) {
mContext = context;
@@ -145,6 +179,7 @@
mIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ mIntentFilter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
mContext.registerReceiver(mReceiver, mIntentFilter);
mAudioDevices = new HashMap<BluetoothDevice, Integer>();
@@ -551,4 +586,6 @@
private synchronized native boolean suspendSinkNative(String path);
private synchronized native boolean resumeSinkNative(String path);
private synchronized native Object []getSinkPropertiesNative(String path);
+ private synchronized native boolean avrcpVolumeUpNative(String path);
+ private synchronized native boolean avrcpVolumeDownNative(String path);
}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index afc6864..1023036 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -39,6 +39,8 @@
*/
public abstract class Layout {
private static final boolean DEBUG = false;
+ private static final ParagraphStyle[] NO_PARA_SPANS =
+ ArrayUtils.emptyArray(ParagraphStyle.class);
/* package */ static final EmojiFactory EMOJI_FACTORY =
EmojiFactory.newAvailableInstance();
@@ -57,7 +59,7 @@
private RectF mEmojiRect;
/**
- * Return how wide a layout would be necessary to display the
+ * Return how wide a layout must be in order to display the
* specified text with one line per paragraph.
*/
public static float getDesiredWidth(CharSequence source,
@@ -66,7 +68,7 @@
}
/**
- * Return how wide a layout would be necessary to display the
+ * Return how wide a layout must be in order to display the
* specified text slice with one line per paragraph.
*/
public static float getDesiredWidth(CharSequence source,
@@ -82,6 +84,7 @@
if (next < 0)
next = end;
+ // note, omits trailing paragraph char
float w = measureText(paint, workPaint,
source, i, next, null, true, null);
@@ -97,10 +100,19 @@
/**
* Subclasses of Layout use this constructor to set the display text,
* width, and other standard properties.
+ * @param text the text to render
+ * @param paint the default paint for the layout. Styles can override
+ * various attributes of the paint.
+ * @param width the wrapping width for the text.
+ * @param align whether to left, right, or center the text. Styles can
+ * override the alignment.
+ * @param spacingMult factor by which to scale the font size to get the
+ * default line spacing
+ * @param spacingAdd amount to add to the default line spacing
*/
protected Layout(CharSequence text, TextPaint paint,
int width, Alignment align,
- float spacingmult, float spacingadd) {
+ float spacingMult, float spacingAdd) {
if (width < 0)
throw new IllegalArgumentException("Layout: " + width + " < 0");
@@ -109,8 +121,8 @@
mWorkPaint = new TextPaint();
mWidth = width;
mAlignment = align;
- mSpacingMult = spacingmult;
- mSpacingAdd = spacingadd;
+ mSpacingMult = spacingMult;
+ mSpacingAdd = spacingAdd;
mSpannedText = text instanceof Spanned;
}
@@ -141,10 +153,16 @@
}
/**
- * Draw the specified rectangle from this Layout on the specified Canvas,
- * with the specified path drawn between the background and the text.
+ * Draw this Layout on the specified canvas, with the highlight path drawn
+ * between the background and the text.
+ *
+ * @param c the canvas
+ * @param highlight the path of the highlight or cursor; can be null
+ * @param highlightPaint the paint for the highlight
+ * @param cursorOffsetVertical the amount to temporarily translate the
+ * canvas while rendering the highlight
*/
- public void draw(Canvas c, Path highlight, Paint highlightpaint,
+ public void draw(Canvas c, Path highlight, Paint highlightPaint,
int cursorOffsetVertical) {
int dtop, dbottom;
@@ -157,13 +175,10 @@
dbottom = sTempRect.bottom;
}
- TextPaint paint = mPaint;
int top = 0;
- // getLineBottom(getLineCount() -1) just calls getLineTop(getLineCount)
int bottom = getLineTop(getLineCount());
-
if (dtop > top) {
top = dtop;
}
@@ -177,16 +192,19 @@
int previousLineBottom = getLineTop(first);
int previousLineEnd = getLineStart(first);
+ TextPaint paint = mPaint;
CharSequence buf = mText;
-
- ParagraphStyle[] nospans = ArrayUtils.emptyArray(ParagraphStyle.class);
- ParagraphStyle[] spans = nospans;
- int spanend = 0;
- int textLength = 0;
+ int width = mWidth;
boolean spannedText = mSpannedText;
+ ParagraphStyle[] spans = NO_PARA_SPANS;
+ int spanend = 0;
+ int textLength = 0;
+
+ // First, draw LineBackgroundSpans.
+ // LineBackgroundSpans know nothing about the alignment or direction of
+ // the layout or line. XXX: Should they?
if (spannedText) {
- spanend = 0;
textLength = buf.length();
for (int i = first; i <= last; i++) {
int start = previousLineEnd;
@@ -209,7 +227,7 @@
for (int n = 0; n < spans.length; n++) {
LineBackgroundSpan back = (LineBackgroundSpan) spans[n];
- back.drawBackground(c, paint, 0, mWidth,
+ back.drawBackground(c, paint, 0, width,
ltop, lbaseline, lbottom,
buf, start, end,
i);
@@ -219,7 +237,7 @@
spanend = 0;
previousLineBottom = getLineTop(first);
previousLineEnd = getLineStart(first);
- spans = nospans;
+ spans = NO_PARA_SPANS;
}
// There can be a highlight even without spans if we are drawing
@@ -229,7 +247,7 @@
c.translate(0, cursorOffsetVertical);
}
- c.drawPath(highlight, highlightpaint);
+ c.drawPath(highlight, highlightPaint);
if (cursorOffsetVertical != 0) {
c.translate(0, -cursorOffsetVertical);
@@ -238,6 +256,9 @@
Alignment align = mAlignment;
+ // Next draw the lines, one at a time.
+ // the baseline is the top of the following line minus the current
+ // line's descent.
for (int i = first; i <= last; i++) {
int start = previousLineEnd;
@@ -249,21 +270,20 @@
previousLineBottom = lbottom;
int lbaseline = lbottom - getLineDescent(i);
- boolean par = false;
+ boolean isFirstParaLine = false;
if (spannedText) {
if (start == 0 || buf.charAt(start - 1) == '\n') {
- par = true;
+ isFirstParaLine = true;
}
+ // New batch of paragraph styles, compute the alignment.
+ // Last alignment style wins.
if (start >= spanend) {
-
Spanned sp = (Spanned) buf;
-
spanend = sp.nextSpanTransition(start, textLength,
ParagraphStyle.class);
spans = sp.getSpans(start, spanend, ParagraphStyle.class);
align = mAlignment;
-
for (int n = spans.length-1; n >= 0; n--) {
if (spans[n] instanceof AlignmentSpan) {
align = ((AlignmentSpan) spans[n]).getAlignment();
@@ -277,6 +297,8 @@
int left = 0;
int right = mWidth;
+ // Draw all leading margin spans. Adjust left or right according
+ // to the paragraph direction of the line.
if (spannedText) {
final int length = spans.length;
for (int n = 0; n < length; n++) {
@@ -286,15 +308,15 @@
if (dir == DIR_RIGHT_TO_LEFT) {
margin.drawLeadingMargin(c, paint, right, dir, ltop,
lbaseline, lbottom, buf,
- start, end, par, this);
+ start, end, isFirstParaLine, this);
- right -= margin.getLeadingMargin(par);
+ right -= margin.getLeadingMargin(isFirstParaLine);
} else {
margin.drawLeadingMargin(c, paint, left, dir, ltop,
lbaseline, lbottom, buf,
- start, end, par, this);
+ start, end, isFirstParaLine, this);
- boolean useMargin = par;
+ boolean useMargin = isFirstParaLine;
if (margin instanceof LeadingMarginSpan.LeadingMarginSpan2) {
int count = ((LeadingMarginSpan.LeadingMarginSpan2)margin).getLeadingMarginLineCount();
useMargin = count > i;
@@ -305,6 +327,8 @@
}
}
+ // Adjust the point at which to start rendering depending on the
+ // alignment of the paragraph.
int x;
if (align == Alignment.ALIGN_NORMAL) {
if (dir == DIR_LEFT_TO_RIGHT) {
@@ -340,6 +364,7 @@
Assert.assertTrue(dir == DIR_LEFT_TO_RIGHT);
Assert.assertNotNull(c);
}
+ // XXX: assumes there's nothing additional to be done
c.drawText(buf, start, end, x, lbaseline, paint);
} else {
drawText(c, buf, start, end, dir, directions,
@@ -382,7 +407,7 @@
/**
* Increase the width of this layout to the specified width.
- * Be careful to use this only when you know it is appropriate --
+ * Be careful to use this only when you know it is appropriate—
* it does not cause the text to reflow to use the full new width.
*/
public final void increaseWidthTo(int wid) {
@@ -397,7 +422,7 @@
* Return the total height of this layout.
*/
public int getHeight() {
- return getLineTop(getLineCount()); // same as getLineBottom(getLineCount() - 1);
+ return getLineTop(getLineCount());
}
/**
@@ -439,33 +464,35 @@
bounds.left = 0; // ???
bounds.top = getLineTop(line);
bounds.right = mWidth; // ???
- bounds.bottom = getLineBottom(line);
+ bounds.bottom = getLineTop(line + 1);
}
return getLineBaseline(line);
}
/**
- * Return the vertical position of the top of the specified line.
- * If the specified line is one beyond the last line, returns the
+ * Return the vertical position of the top of the specified line
+ * (0…getLineCount()).
+ * If the specified line is equal to the line count, returns the
* bottom of the last line.
*/
public abstract int getLineTop(int line);
/**
- * Return the descent of the specified line.
+ * Return the descent of the specified line(0…getLineCount() - 1).
*/
public abstract int getLineDescent(int line);
/**
- * Return the text offset of the beginning of the specified line.
- * If the specified line is one beyond the last line, returns the
- * end of the last line.
+ * Return the text offset of the beginning of the specified line (
+ * 0…getLineCount()). If the specified line is equal to the line
+ * count, returns the length of the text.
*/
public abstract int getLineStart(int line);
/**
- * Returns the primary directionality of the paragraph containing
- * the specified line.
+ * Returns the primary directionality of the paragraph containing the
+ * specified line, either 1 for left-to-right lines, or -1 for right-to-left
+ * lines (see {@link #DIR_LEFT_TO_RIGHT}, {@link #DIR_RIGHT_TO_LEFT}).
*/
public abstract int getParagraphDirection(int line);
@@ -477,9 +504,11 @@
public abstract boolean getLineContainsTab(int line);
/**
- * Returns an array of directionalities for the specified line.
+ * Returns the directional run information for the specified line.
* The array alternates counts of characters in left-to-right
* and right-to-left segments of the line.
+ *
+ * <p>NOTE: this is inadequate to support bidirectional text, and will change.
*/
public abstract Directions getLineDirections(int line);
@@ -1565,6 +1594,21 @@
return h;
}
+ /**
+ * Measure width of a run of text on a single line that is known to all be
+ * in the same direction as the paragraph base direction. Returns the width,
+ * and the line metrics in fm if fm is not null.
+ *
+ * @param paint the paint for the text; will not be modified
+ * @param workPaint paint available for modification
+ * @param text text
+ * @param start start of the line
+ * @param end limit of the line
+ * @param fm object to return integer metrics in, can be null
+ * @param hasTabs true if it is known that the line has tabs
+ * @param tabs tab position information
+ * @return the width of the text from start to end
+ */
/* package */ static float measureText(TextPaint paint,
TextPaint workPaint,
CharSequence text,
@@ -1580,37 +1624,36 @@
int len = end - start;
- int here = 0;
- float h = 0;
- int ab = 0, be = 0;
- int top = 0, bot = 0;
+ int lastPos = 0;
+ float width = 0;
+ int ascent = 0, descent = 0, top = 0, bottom = 0;
if (fm != null) {
fm.ascent = 0;
fm.descent = 0;
}
- for (int i = hasTabs ? 0 : len; i <= len; i++) {
+ for (int pos = hasTabs ? 0 : len; pos <= len; pos++) {
int codept = 0;
Bitmap bm = null;
- if (hasTabs && i < len) {
- codept = buf[i];
+ if (hasTabs && pos < len) {
+ codept = buf[pos];
}
- if (codept >= 0xD800 && codept <= 0xDFFF && i < len) {
- codept = Character.codePointAt(buf, i);
+ if (codept >= 0xD800 && codept <= 0xDFFF && pos < len) {
+ codept = Character.codePointAt(buf, pos);
if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) {
bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept);
}
}
- if (i == len || codept == '\t' || bm != null) {
+ if (pos == len || codept == '\t' || bm != null) {
workPaint.baselineShift = 0;
- h += Styled.measureText(paint, workPaint, text,
- start + here, start + i,
+ width += Styled.measureText(paint, workPaint, text,
+ start + lastPos, start + pos,
fm);
if (fm != null) {
@@ -1623,60 +1666,80 @@
}
}
- if (i != len) {
+ if (pos != len) {
if (bm == null) {
- h = nextTab(text, start, end, h, tabs);
+ // no emoji, must have hit a tab
+ width = nextTab(text, start, end, width, tabs);
} else {
+ // This sets up workPaint with the font on the emoji
+ // text, so that we can extract the ascent and scale.
+
+ // We can't use the result of the previous call to
+ // measureText because the emoji might have its own style.
+ // We have to initialize workPaint here because if the
+ // text is unstyled measureText might not use workPaint
+ // at all.
workPaint.set(paint);
Styled.measureText(paint, workPaint, text,
- start + i, start + i + 1, null);
+ start + pos, start + pos + 1, null);
- float wid = (float) bm.getWidth() *
+ width += (float) bm.getWidth() *
-workPaint.ascent() / bm.getHeight();
- h += wid;
- i++;
+ // Since we had an emoji, we bump past the second half
+ // of the surrogate pair.
+ pos++;
}
}
if (fm != null) {
- if (fm.ascent < ab) {
- ab = fm.ascent;
+ if (fm.ascent < ascent) {
+ ascent = fm.ascent;
}
- if (fm.descent > be) {
- be = fm.descent;
+ if (fm.descent > descent) {
+ descent = fm.descent;
}
if (fm.top < top) {
top = fm.top;
}
- if (fm.bottom > bot) {
- bot = fm.bottom;
+ if (fm.bottom > bottom) {
+ bottom = fm.bottom;
}
- /*
- * No need to take bitmap height into account here,
- * since it is scaled to match the text height.
- */
+ // No need to take bitmap height into account here,
+ // since it is scaled to match the text height.
}
- here = i + 1;
+ lastPos = pos + 1;
}
}
if (fm != null) {
- fm.ascent = ab;
- fm.descent = be;
+ fm.ascent = ascent;
+ fm.descent = descent;
fm.top = top;
- fm.bottom = bot;
+ fm.bottom = bottom;
}
if (hasTabs)
TextUtils.recycle(buf);
- return h;
+ return width;
}
+ /**
+ * Returns the position of the next tab stop after h on the line.
+ *
+ * @param text the text
+ * @param start start of the line
+ * @param end limit of the line
+ * @param h the current horizontal offset
+ * @param tabs the tabs, can be null. If it is null, any tabs in effect
+ * on the line will be used. If there are no tabs, a default offset
+ * will be used to compute the tab stop.
+ * @return the offset of the next tab stop.
+ */
/* package */ static float nextTab(CharSequence text, int start, int end,
float h, Object[] tabs) {
float nh = Float.MAX_VALUE;
@@ -1747,6 +1810,16 @@
public static class Directions {
private short[] mDirections;
+ // The values in mDirections are the offsets from the first character
+ // in the line to the next flip in direction. Runs at even indices
+ // are left-to-right, the others are right-to-left. So, for example,
+ // a line that starts with a right-to-left run has 0 at mDirections[0],
+ // since the 'first' (ltr) run is zero length.
+ //
+ // The code currently assumes that each run is adjacent to the previous
+ // one, progressing in the base line direction. This isn't sufficient
+ // to handle nested runs, for example numeric text in an rtl context
+ // in an ltr paragraph.
/* package */ Directions(short[] dirs) {
mDirections = dirs;
}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index fbf1261..6c89f92 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -1012,6 +1012,10 @@
int extra;
if (needMultiply) {
+ // XXX: this looks like it is using the +0.5 and the cast to int
+ // to do rounding, but this I expect this isn't doing the intended
+ // thing when spacingmult < 1. An intended extra of, say, -1.2
+ // will get 'rounded' to -.7 and then truncated to 0.
extra = (int) ((below - above) * (spacingmult - 1)
+ spacingadd + 0.5);
} else {
diff --git a/core/java/android/text/Styled.java b/core/java/android/text/Styled.java
index 0aa2004..513b2cd 100644
--- a/core/java/android/text/Styled.java
+++ b/core/java/android/text/Styled.java
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package android.text;
import android.graphics.Canvas;
@@ -23,27 +22,49 @@
import android.text.style.ReplacementSpan;
/**
- * This class provides static methods for drawing and measuring styled texts, like
- * {@link android.text.Spanned} object with {@link android.text.style.ReplacementSpan}.
+ * This class provides static methods for drawing and measuring styled text,
+ * like {@link android.text.Spanned} object with
+ * {@link android.text.style.ReplacementSpan}.
+ *
* @hide
*/
public class Styled
{
- private static float each(Canvas canvas,
+ /**
+ * Draws and/or measures a uniform run of text on a single line. No span of
+ * interest should start or end in the middle of this run (if not
+ * drawing, character spans that don't affect metrics can be ignored).
+ * Neither should the run direction change in the middle of the run.
+ *
+ * <p>The x position is the leading edge of the text. In a right-to-left
+ * paragraph, this will be to the right of the text to be drawn. Paint
+ * should not have an Align value other than LEFT or positioning will get
+ * confused.
+ *
+ * <p>On return, workPaint will reflect the original paint plus any
+ * modifications made by character styles on the run.
+ *
+ * <p>The returned width is signed and will be < 0 if the paragraph
+ * direction is right-to-left.
+ */
+ private static float drawUniformRun(Canvas canvas,
Spanned text, int start, int end,
- int dir, boolean reverse,
+ int dir, boolean runIsRtl,
float x, int top, int y, int bottom,
Paint.FontMetricsInt fmi,
TextPaint paint,
TextPaint workPaint,
- boolean needwid) {
+ boolean needWidth) {
- boolean havewid = false;
+ boolean haveWidth = false;
float ret = 0;
CharacterStyle[] spans = text.getSpans(start, end, CharacterStyle.class);
ReplacementSpan replacement = null;
+ // XXX: This shouldn't be modifying paint, only workPaint.
+ // However, the members belonging to TextPaint should have default
+ // values anyway. Better to ensure this in the Layout constructor.
paint.bgColor = 0;
paint.baselineShift = 0;
workPaint.set(paint);
@@ -65,9 +86,10 @@
CharSequence tmp;
int tmpstart, tmpend;
- if (reverse) {
+ if (runIsRtl) {
tmp = TextUtils.getReverse(text, start, end);
tmpstart = 0;
+ // XXX: assumes getReverse doesn't change the length of the text
tmpend = end - start;
} else {
tmp = text;
@@ -86,9 +108,9 @@
workPaint.setColor(workPaint.bgColor);
workPaint.setStyle(Paint.Style.FILL);
- if (!havewid) {
+ if (!haveWidth) {
ret = workPaint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
+ haveWidth = true;
}
if (dir == Layout.DIR_RIGHT_TO_LEFT)
@@ -101,18 +123,18 @@
}
if (dir == Layout.DIR_RIGHT_TO_LEFT) {
- if (!havewid) {
+ if (!haveWidth) {
ret = workPaint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
+ haveWidth = true;
}
canvas.drawText(tmp, tmpstart, tmpend,
x - ret, y + workPaint.baselineShift, workPaint);
} else {
- if (needwid) {
- if (!havewid) {
+ if (needWidth) {
+ if (!haveWidth) {
ret = workPaint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
+ haveWidth = true;
}
}
@@ -120,9 +142,9 @@
x, y + workPaint.baselineShift, workPaint);
}
} else {
- if (needwid && !havewid) {
+ if (needWidth && !haveWidth) {
ret = workPaint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
+ haveWidth = true;
}
}
} else {
@@ -145,25 +167,28 @@
}
/**
- * Return the advance widths for the characters in the string.
- * See also {@link android.graphics.Paint#getTextWidths(CharSequence, int, int, float[])}.
+ * Returns the advance widths for a uniform left-to-right run of text with
+ * no style changes in the middle of the run. If any style is replacement
+ * text, the first character will get the width of the replacement and the
+ * remaining characters will get a width of 0.
*
- * @param paint The main {@link TextPaint} object.
- * @param workPaint The {@link TextPaint} object used for temporal workspace.
- * @param text The text to measure
- * @param start The index of the first char to to measure
- * @param end The end of the text slice to measure
- * @param widths Array to receive the advance widths of the characters.
- * Must be at least a large as (end - start).
- * @param fmi FontMetrics information. Can be null.
- * @return The actual number of widths returned.
+ * @param paint the paint, will not be modified
+ * @param workPaint a paint to modify; on return will reflect the original
+ * paint plus the effect of all spans on the run
+ * @param text the text
+ * @param start the start of the run
+ * @param end the limit of the run
+ * @param widths array to receive the advance widths of the characters. Must
+ * be at least a large as (end - start).
+ * @param fmi FontMetrics information; can be null
+ * @return the actual number of widths returned
*/
public static int getTextWidths(TextPaint paint,
TextPaint workPaint,
Spanned text, int start, int end,
float[] widths, Paint.FontMetricsInt fmi) {
- // Keep workPaint as is so that developers reuse the workspace.
- MetricAffectingSpan[] spans = text.getSpans(start, end, MetricAffectingSpan.class);
+ MetricAffectingSpan[] spans =
+ text.getSpans(start, end, MetricAffectingSpan.class);
ReplacementSpan replacement = null;
workPaint.set(paint);
@@ -186,7 +211,6 @@
if (end > start) {
widths[0] = wid;
-
for (int i = start + 1; i < end; i++)
widths[i - start] = 0;
}
@@ -194,19 +218,42 @@
return end - start;
}
- private static float foreach(Canvas canvas,
+ /**
+ * Renders and/or measures a directional run of text on a single line.
+ * Unlike {@link #drawUniformRun}, this can render runs that cross style
+ * boundaries. Returns the signed advance width, if requested.
+ *
+ * <p>The x position is the leading edge of the text. In a right-to-left
+ * paragraph, this will be to the right of the text to be drawn. Paint
+ * should not have an Align value other than LEFT or positioning will get
+ * confused.
+ *
+ * <p>This optimizes for unstyled text and so workPaint might not be
+ * modified by this call.
+ *
+ * <p>The returned advance width will be < 0 if the paragraph
+ * direction is right-to-left.
+ */
+ private static float drawDirectionalRun(Canvas canvas,
CharSequence text, int start, int end,
- int dir, boolean reverse,
+ int dir, boolean runIsRtl,
float x, int top, int y, int bottom,
Paint.FontMetricsInt fmi,
TextPaint paint,
TextPaint workPaint,
boolean needWidth) {
- if (! (text instanceof Spanned)) {
+
+ // XXX: It looks like all calls to this API match dir and runIsRtl, so
+ // having both parameters is redundant and confusing.
+
+ // fast path for unstyled text
+ if (!(text instanceof Spanned)) {
float ret = 0;
- if (reverse) {
+ if (runIsRtl) {
CharSequence tmp = TextUtils.getReverse(text, start, end);
+ // XXX: this assumes getReverse doesn't tweak the length of
+ // the text
int tmpend = end - start;
if (canvas != null || needWidth)
@@ -227,15 +274,14 @@
paint.getFontMetricsInt(fmi);
}
- return ret * dir; //Layout.DIR_RIGHT_TO_LEFT == -1
+ return ret * dir; // Layout.DIR_RIGHT_TO_LEFT == -1
}
float ox = x;
- int asc = 0, desc = 0;
- int ftop = 0, fbot = 0;
+ int minAscent = 0, maxDescent = 0, minTop = 0, maxBottom = 0;
Spanned sp = (Spanned) text;
- Class division;
+ Class<?> division;
if (canvas == null)
division = MetricAffectingSpan.class;
@@ -246,20 +292,23 @@
for (int i = start; i < end; i = next) {
next = sp.nextSpanTransition(i, end, division);
- x += each(canvas, sp, i, next, dir, reverse,
+ // XXX: if dir and runIsRtl were not the same, this would draw
+ // spans in the wrong order, but no one appears to call it this
+ // way.
+ x += drawUniformRun(canvas, sp, i, next, dir, runIsRtl,
x, top, y, bottom, fmi, paint, workPaint,
needWidth || next != end);
if (fmi != null) {
- if (fmi.ascent < asc)
- asc = fmi.ascent;
- if (fmi.descent > desc)
- desc = fmi.descent;
+ if (fmi.ascent < minAscent)
+ minAscent = fmi.ascent;
+ if (fmi.descent > maxDescent)
+ maxDescent = fmi.descent;
- if (fmi.top < ftop)
- ftop = fmi.top;
- if (fmi.bottom > fbot)
- fbot = fmi.bottom;
+ if (fmi.top < minTop)
+ minTop = fmi.top;
+ if (fmi.bottom > maxBottom)
+ maxBottom = fmi.bottom;
}
}
@@ -267,71 +316,78 @@
if (start == end) {
paint.getFontMetricsInt(fmi);
} else {
- fmi.ascent = asc;
- fmi.descent = desc;
- fmi.top = ftop;
- fmi.bottom = fbot;
+ fmi.ascent = minAscent;
+ fmi.descent = maxDescent;
+ fmi.top = minTop;
+ fmi.bottom = maxBottom;
}
}
return x - ox;
}
-
+ /**
+ * Draws a unidirectional run of text on a single line, and optionally
+ * returns the signed advance. Unlike drawDirectionalRun, the paragraph
+ * direction and run direction can be different.
+ */
/* package */ static float drawText(Canvas canvas,
CharSequence text, int start, int end,
- int direction, boolean reverse,
+ int dir, boolean runIsRtl,
float x, int top, int y, int bottom,
TextPaint paint,
TextPaint workPaint,
boolean needWidth) {
- if ((direction == Layout.DIR_RIGHT_TO_LEFT && !reverse) ||
- (reverse && direction == Layout.DIR_LEFT_TO_RIGHT)) {
- float ch = foreach(null, text, start, end, Layout.DIR_LEFT_TO_RIGHT,
- false, 0, 0, 0, 0, null, paint, workPaint,
- true);
+ // XXX this logic is (dir == DIR_LEFT_TO_RIGHT) == runIsRtl
+ if ((dir == Layout.DIR_RIGHT_TO_LEFT && !runIsRtl) ||
+ (runIsRtl && dir == Layout.DIR_LEFT_TO_RIGHT)) {
+ // TODO: this needs the real direction
+ float ch = drawDirectionalRun(null, text, start, end,
+ Layout.DIR_LEFT_TO_RIGHT, false, 0, 0, 0, 0, null, paint,
+ workPaint, true);
- ch *= direction; // DIR_RIGHT_TO_LEFT == -1
- foreach(canvas, text, start, end, -direction,
- reverse, x + ch, top, y, bottom, null, paint,
+ ch *= dir; // DIR_RIGHT_TO_LEFT == -1
+ drawDirectionalRun(canvas, text, start, end, -dir,
+ runIsRtl, x + ch, top, y, bottom, null, paint,
workPaint, true);
return ch;
}
- return foreach(canvas, text, start, end, direction, reverse,
+ return drawDirectionalRun(canvas, text, start, end, dir, runIsRtl,
x, top, y, bottom, null, paint, workPaint,
needWidth);
}
/**
- * Draw the specified range of text, specified by start/end, with its origin at (x,y),
- * in the specified Paint. The origin is interpreted based on the Align setting in the
- * Paint.
- *
- * This method considers style information in the text
- * (e.g. Even when text is an instance of {@link android.text.Spanned}, this method
- * correctly draws the text).
- * See also
- * {@link android.graphics.Canvas#drawText(CharSequence, int, int, float, float, Paint)}
- * and
- * {@link android.graphics.Canvas#drawRect(float, float, float, float, Paint)}.
+ * Draws a run of text on a single line, with its
+ * origin at (x,y), in the specified Paint. The origin is interpreted based
+ * on the Align setting in the Paint.
+ *
+ * This method considers style information in the text (e.g. even when text
+ * is an instance of {@link android.text.Spanned}, this method correctly
+ * draws the text). See also
+ * {@link android.graphics.Canvas#drawText(CharSequence, int, int, float,
+ * float, Paint)} and
+ * {@link android.graphics.Canvas#drawRect(float, float, float, float,
+ * Paint)}.
*
- * @param canvas The target canvas.
+ * @param canvas The target canvas
* @param text The text to be drawn
* @param start The index of the first character in text to draw
* @param end (end - 1) is the index of the last character in text to draw
* @param direction The direction of the text. This must be
- * {@link android.text.Layout#DIR_LEFT_TO_RIGHT} or
- * {@link android.text.Layout#DIR_RIGHT_TO_LEFT}.
+ * {@link android.text.Layout#DIR_LEFT_TO_RIGHT} or
+ * {@link android.text.Layout#DIR_RIGHT_TO_LEFT}.
* @param x The x-coordinate of origin for where to draw the text
* @param top The top side of the rectangle to be drawn
* @param y The y-coordinate of origin for where to draw the text
* @param bottom The bottom side of the rectangle to be drawn
* @param paint The main {@link TextPaint} object.
- * @param workPaint The {@link TextPaint} object used for temporal workspace.
- * @param needWidth If true, this method returns the width of drawn text.
- * @return Width of the drawn text if needWidth is true.
+ * @param workPaint The {@link TextPaint} object used for temporal
+ * workspace.
+ * @param needWidth If true, this method returns the width of drawn text
+ * @return Width of the drawn text if needWidth is true
*/
public static float drawText(Canvas canvas,
CharSequence text, int start, int end,
@@ -341,34 +397,37 @@
TextPaint workPaint,
boolean needWidth) {
// For safety.
- direction = direction >= 0 ? Layout.DIR_LEFT_TO_RIGHT : Layout.DIR_RIGHT_TO_LEFT;
- /*
- * Hided "reverse" parameter since it is meaningless for external developers.
- * Kept workPaint as is so that developers reuse the workspace.
- */
+ direction = direction >= 0 ? Layout.DIR_LEFT_TO_RIGHT
+ : Layout.DIR_RIGHT_TO_LEFT;
+
+ // Hide runIsRtl parameter since it is meaningless for external
+ // developers.
+ // XXX: the runIsRtl probably ought to be the same as direction, then
+ // this could draw rtl text.
return drawText(canvas, text, start, end, direction, false,
x, top, y, bottom, paint, workPaint, needWidth);
}
/**
- * Return the width of the text, considering style information in the text
- * (e.g. Even when text is an instance of {@link android.text.Spanned}, this method
- * correctly mesures the width of the text).
+ * Returns the width of a run of left-to-right text on a single line,
+ * considering style information in the text (e.g. even when text is an
+ * instance of {@link android.text.Spanned}, this method correctly measures
+ * the width of the text).
*
- * @param paint The main {@link TextPaint} object.
- * @param workPaint The {@link TextPaint} object used for temporal workspace.
- * @param text The text to measure
- * @param start The index of the first character to start measuring
+ * @param paint the main {@link TextPaint} object; will not be modified
+ * @param workPaint the {@link TextPaint} object available for modification;
+ * will not necessarily be used
+ * @param text the text to measure
+ * @param start the index of the first character to start measuring
* @param end 1 beyond the index of the last character to measure
- * @param fmi FontMetrics information. Can be null
- * @return The width of the text
+ * @param fmi FontMetrics information; can be null
+ * @return The width of the text
*/
public static float measureText(TextPaint paint,
TextPaint workPaint,
CharSequence text, int start, int end,
Paint.FontMetricsInt fmi) {
- // Keep workPaint as is so that developers reuse the workspace.
- return foreach(null, text, start, end,
+ return drawDirectionalRun(null, text, start, end,
Layout.DIR_LEFT_TO_RIGHT, false,
0, 0, 0, 0, fmi, paint, workPaint, true);
}
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
index cb55329..6635ddb8 100644
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ b/core/java/android/text/style/LeadingMarginSpan.java
@@ -23,10 +23,44 @@
import android.text.ParcelableSpan;
import android.text.TextUtils;
+/**
+ * A paragraph style affecting the leading margin. There can be multiple leading
+ * margin spans on a single paragraph; they will be rendered in order, each
+ * adding its margin to the ones before it. The leading margin is on the right
+ * for lines in a right-to-left paragraph.
+ */
public interface LeadingMarginSpan
extends ParagraphStyle
{
+ /**
+ * Returns the amount by which to adjust the leading margin. Positive values
+ * move away from the leading edge of the paragraph, negative values move
+ * towards it.
+ *
+ * @param first true if the request is for the first line of a paragraph,
+ * false for subsequent lines
+ * @return the offset for the margin.
+ */
public int getLeadingMargin(boolean first);
+
+ /**
+ * Renders the leading margin. This is called before the margin has been
+ * adjusted by the value returned by {@link getLeadingMargin(boolean)}.
+ *
+ * @param c the canvas
+ * @param p the paint. The this should be left unchanged on exit.
+ * @param x the current position of the margin
+ * @param dir the base direction of the paragraph; if negative, the margin
+ * is to the right of the text, otherwise it is to the left.
+ * @param top the top of the line
+ * @param baseline the baseline of the line
+ * @param bottom the bottom of the line
+ * @param text the text
+ * @param start the start of the line
+ * @param end the end of the line
+ * @param first true if this is the first line of its paragraph
+ * @param layout the layout containing this line
+ */
public void drawLeadingMargin(Canvas c, Paint p,
int x, int dir,
int top, int baseline, int bottom,
@@ -38,14 +72,29 @@
public int getLeadingMarginLineCount();
};
+ /**
+ * The standard implementation of LeadingMarginSpan, which adjusts the
+ * margin but does not do any rendering.
+ */
public static class Standard implements LeadingMarginSpan, ParcelableSpan {
private final int mFirst, mRest;
+ /**
+ * Constructor taking separate indents for the first and subsequent
+ * lines.
+ *
+ * @param first the indent for the first line of the paragraph
+ * @param rest the indent for the remaining lines of the paragraph
+ */
public Standard(int first, int rest) {
mFirst = first;
mRest = rest;
}
+ /**
+ * Constructor taking an indent for all lines.
+ * @param every the indent of each line
+ */
public Standard(int every) {
this(every, every);
}
diff --git a/core/java/android/text/style/TabStopSpan.java b/core/java/android/text/style/TabStopSpan.java
index e5b7644..0566428 100644
--- a/core/java/android/text/style/TabStopSpan.java
+++ b/core/java/android/text/style/TabStopSpan.java
@@ -16,14 +16,31 @@
package android.text.style;
+/**
+ * Represents a single tab stop on a line.
+ */
public interface TabStopSpan
extends ParagraphStyle
{
+ /**
+ * Returns the offset of the tab stop from the leading margin of the
+ * line.
+ * @return the offset
+ */
public int getTabStop();
+ /**
+ * The default implementation of TabStopSpan.
+ */
public static class Standard
implements TabStopSpan
{
+ /**
+ * Constructor.
+ *
+ * @param where the offset of the tab stop from the leading margin of
+ * the line
+ */
public Standard(int where) {
mTab = where;
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 9e9cc7e..d1ad61f 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -116,7 +116,7 @@
* @param webView The WebView that created this.
*/
/* package */ WebTextView(Context context, WebView webView) {
- super(context);
+ super(context, null, com.android.internal.R.attr.webTextViewStyle);
mWebView = webView;
mMaxLength = -1;
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index ae6c666..9672892 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1102,7 +1102,7 @@
* methods may be called on a WebView after destroy.
*/
public void destroy() {
- clearTextEntry();
+ clearTextEntry(false);
if (mWebViewCore != null) {
// Set the handlers to null before destroying WebViewCore so no
// more messages will be posted.
@@ -1388,7 +1388,7 @@
arg.mUrl = url;
arg.mExtraHeaders = extraHeaders;
mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);
- clearTextEntry();
+ clearTextEntry(false);
}
/**
@@ -1417,7 +1417,7 @@
arg.mUrl = url;
arg.mPostData = postData;
mWebViewCore.sendMessage(EventHub.POST_URL, arg);
- clearTextEntry();
+ clearTextEntry(false);
} else {
loadUrl(url);
}
@@ -1473,7 +1473,7 @@
arg.mEncoding = encoding;
arg.mFailUrl = failUrl;
mWebViewCore.sendMessage(EventHub.LOAD_DATA, arg);
- clearTextEntry();
+ clearTextEntry(false);
}
/**
@@ -1490,7 +1490,7 @@
* Reload the current url.
*/
public void reload() {
- clearTextEntry();
+ clearTextEntry(false);
switchOutDrawHistory();
mWebViewCore.sendMessage(EventHub.RELOAD);
}
@@ -1577,7 +1577,7 @@
// null, and that will be the case
mCertificate = null;
if (steps != 0) {
- clearTextEntry();
+ clearTextEntry(false);
mWebViewCore.sendMessage(EventHub.GO_BACK_FORWARD, steps,
ignoreSnapshot ? 1 : 0);
}
@@ -1677,9 +1677,17 @@
&& mWebTextView.hasFocus();
}
- private void clearTextEntry() {
+ /**
+ * Remove the WebTextView.
+ * @param disableFocusController If true, send a message to webkit
+ * disabling the focus controller, so the caret stops blinking.
+ */
+ private void clearTextEntry(boolean disableFocusController) {
if (inEditingMode()) {
mWebTextView.remove();
+ if (disableFocusController) {
+ setFocusControllerInactive();
+ }
}
}
@@ -1713,7 +1721,7 @@
Log.w(LOGTAG, "This WebView doesn't support zoom.");
return;
}
- clearTextEntry();
+ clearTextEntry(false);
if (getSettings().getBuiltInZoomControls()) {
mZoomButtonsController.setVisible(true);
} else {
@@ -3105,11 +3113,26 @@
}
}
+ private static class Metrics {
+ int mScrollX;
+ int mScrollY;
+ int mWidth;
+ int mHeight;
+ float mScale;
+ }
+
+ private Metrics getViewMetrics() {
+ Metrics metrics = new Metrics();
+ metrics.mScrollX = mScrollX;
+ metrics.mScrollY = computeVerticalScrollOffset();
+ metrics.mWidth = getWidth();
+ metrics.mHeight = getHeight() - getVisibleTitleHeight();
+ metrics.mScale = mActualScale;
+ return metrics;
+ }
+
private void drawLayers(Canvas canvas) {
if (mRootLayer != 0) {
- int scrollY = computeVerticalScrollOffset();
- int viewHeight = getHeight() - getVisibleTitleHeight();
-
// Currently for each draw we compute the animation values;
// We may in the future decide to do that independently.
if (nativeEvaluateLayersAnimations(mRootLayer)) {
@@ -3119,9 +3142,7 @@
}
// We can now draw the layers.
- nativeDrawLayers(mRootLayer, mScrollX, scrollY,
- getWidth(), viewHeight,
- mActualScale, canvas);
+ nativeDrawLayers(mRootLayer, canvas);
}
}
@@ -3209,7 +3230,15 @@
mWebViewCore.drawContentPicture(canvas, color,
(animateZoom || mPreviewZoomOnly), animateScroll);
-
+ boolean cursorIsInLayer = nativeCursorIsInLayer();
+ if (drawCursorRing && !cursorIsInLayer) {
+ nativeDrawCursorRing(canvas);
+ }
+ // When the FindDialog is up, only draw the matches if we are not in
+ // the process of scrolling them into view.
+ if (mFindIsUp && !animateScroll) {
+ nativeDrawMatches(canvas);
+ }
drawLayers(canvas);
if (mNativeClass == 0) return;
@@ -3232,12 +3261,7 @@
LONG_PRESS_TIMEOUT);
}
}
- nativeDrawCursorRing(canvas);
- }
- // When the FindDialog is up, only draw the matches if we are not in
- // the process of scrolling them into view.
- if (mFindIsUp && !animateScroll) {
- nativeDrawMatches(canvas);
+ if (cursorIsInLayer) nativeDrawCursorRing(canvas);
}
if (mFocusSizeChanged) {
mFocusSizeChanged = false;
@@ -3743,6 +3767,7 @@
}
return true;
}
+ clearTextEntry(true);
nativeSetFollowedLink(true);
if (!mCallbackProxy.uiOverrideUrlLoading(nativeCursorText())) {
mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
@@ -3823,7 +3848,7 @@
@Override
protected void onDetachedFromWindow() {
- clearTextEntry();
+ clearTextEntry(false);
super.onDetachedFromWindow();
// Clean up the zoom controller
mZoomButtonsController.setVisible(false);
@@ -5810,7 +5835,7 @@
// is necessary for page loads driven by webkit, and in
// particular when the user was on a password field, so
// the WebTextView was visible.
- clearTextEntry();
+ clearTextEntry(false);
// update the zoom buttons as the scale can be changed
if (getSettings().getBuiltInZoomControls()) {
updateZoomButtonsEnabled();
@@ -5932,7 +5957,7 @@
}
break;
case CLEAR_TEXT_ENTRY:
- clearTextEntry();
+ clearTextEntry(false);
break;
case INVAL_RECT_MSG_ID: {
Rect r = (Rect)msg.obj;
@@ -5952,6 +5977,7 @@
case SET_ROOT_LAYER_MSG_ID: {
int oldLayer = mRootLayer;
mRootLayer = msg.arg1;
+ nativeSetRootLayer(mRootLayer);
if (oldLayer > 0) {
nativeDestroyLayer(oldLayer);
}
@@ -6538,8 +6564,7 @@
*/
private void sendMoveMouseIfLatest(boolean removeFocus) {
if (removeFocus) {
- clearTextEntry();
- setFocusControllerInactive();
+ clearTextEntry(true);
}
mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE_IF_LATEST,
cursorData());
@@ -6715,6 +6740,7 @@
/* package */ native boolean nativeCursorMatchesFocus();
private native boolean nativeCursorIntersects(Rect visibleRect);
private native boolean nativeCursorIsAnchor();
+ private native boolean nativeCursorIsInLayer();
private native boolean nativeCursorIsTextInput();
private native Point nativeCursorPosition();
private native String nativeCursorText();
@@ -6728,10 +6754,7 @@
private native void nativeDrawCursorRing(Canvas content);
private native void nativeDestroyLayer(int layer);
private native boolean nativeEvaluateLayersAnimations(int layer);
- private native void nativeDrawLayers(int layer,
- int scrollX, int scrollY,
- int width, int height,
- float scale, Canvas canvas);
+ private native void nativeDrawLayers(int layer, Canvas canvas);
private native void nativeDrawMatches(Canvas canvas);
private native void nativeDrawSelectionPointer(Canvas content,
float scale, int x, int y, boolean extendSelection);
@@ -6781,6 +6804,7 @@
private native void nativeSetFindIsUp();
private native void nativeSetFollowedLink(boolean followed);
private native void nativeSetHeightCanMeasure(boolean measure);
+ private native void nativeSetRootLayer(int layer);
private native int nativeTextGeneration();
// Never call this version except by updateCachedTextfield(String) -
// we always want to pass in our generation number.
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
index 4eab4b3..cf53a06 100644
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ b/core/jni/android_server_BluetoothA2dpService.cpp
@@ -200,6 +200,38 @@
return JNI_FALSE;
}
+static jboolean avrcpVolumeUpNative(JNIEnv *env, jobject object,
+ jstring path) {
+#ifdef HAVE_BLUETOOTH
+ LOGV(__FUNCTION__);
+ if (nat) {
+ const char *c_path = env->GetStringUTFChars(path, NULL);
+ bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
+ c_path, "org.bluez.Control", "VolumeUp",
+ DBUS_TYPE_INVALID);
+ env->ReleaseStringUTFChars(path, c_path);
+ return ret ? JNI_TRUE : JNI_FALSE;
+ }
+#endif
+ return JNI_FALSE;
+}
+
+static jboolean avrcpVolumeDownNative(JNIEnv *env, jobject object,
+ jstring path) {
+#ifdef HAVE_BLUETOOTH
+ LOGV(__FUNCTION__);
+ if (nat) {
+ const char *c_path = env->GetStringUTFChars(path, NULL);
+ bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
+ c_path, "org.bluez.Control", "VolumeDown",
+ DBUS_TYPE_INVALID);
+ env->ReleaseStringUTFChars(path, c_path);
+ return ret ? JNI_TRUE : JNI_FALSE;
+ }
+#endif
+ return JNI_FALSE;
+}
+
#ifdef HAVE_BLUETOOTH
DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env) {
DBusError err;
@@ -267,6 +299,7 @@
free(user);
}
+
#endif
@@ -281,6 +314,8 @@
{"resumeSinkNative", "(Ljava/lang/String;)Z", (void*)resumeSinkNative},
{"getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
(void *)getSinkPropertiesNative},
+ {"avrcpVolumeUpNative", "(Ljava/lang/String;)Z", (void*)avrcpVolumeUpNative},
+ {"avrcpVolumeDownNative", "(Ljava/lang/String;)Z", (void*)avrcpVolumeDownNative},
};
int register_android_server_BluetoothA2dpService(JNIEnv *env) {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ff8cdc9..0f6a5c1 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -396,6 +396,8 @@
<attr name="tabWidgetStyle" format="reference" />
<!-- Default TextView style. -->
<attr name="textViewStyle" format="reference" />
+ <!-- Default WebTextView style. -->
+ <attr name="webTextViewStyle" format="reference" />
<!-- Default WebView style. -->
<attr name="webViewStyle" format="reference" />
<!-- Default style for drop down items. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 70bc000..33b509b 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -83,7 +83,7 @@
never be encrypted if an Encrypted File System solution
is enabled. Specifically, this is an "opt-out" feature, meaning
that, by default, user data will be encrypted if the EFS feature
- is enabled.-->
+ is enabled. -->
<attr name="neverEncrypt" format="boolean" />
<!-- Option to indicate this application is only for testing purposes.
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3c6338e..82c02eb5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1227,9 +1227,9 @@
Resources proposed for Froyo.
=============================================================== -->
<eat-comment />
- <public type="attr" name="neverEncrypt" id="0x010102b7" />
- <public type="attr" name="installLocation" id="0x010102b8" />
- <public type="attr" name="safeMode" id="0x010102b9" />
+ <public type="attr" name="installLocation" id="0x010102b7" />
+ <public type="attr" name="safeMode" id="0x010102b8" />
+ <public type="attr" name="webTextViewStyle" id="0x010102b9" />
<public type="anim" name="cycle_interpolator" id="0x010a000c" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 58e9f45..1287669 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -503,6 +503,17 @@
<item name="android:scrollbars">horizontal|vertical</item>
</style>
+ <style name="Widget.WebTextView">
+ <item name="android:focusable">true</item>
+ <item name="android:focusableInTouchMode">true</item>
+ <item name="android:clickable">true</item>
+ <item name="android:completionHintView">@android:layout/simple_dropdown_item_1line</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceLargeInverse</item>
+ <item name="android:completionThreshold">2</item>
+ <item name="android:dropDownSelector">@android:drawable/list_selector_background</item>
+ <item name="android:popupBackground">@android:drawable/spinner_dropdown_background</item>
+ </style>
+
<style name="Widget.TabWidget">
<item name="android:textAppearance">@style/TextAppearance.Widget.TabWidget</item>
<item name="ellipsize">marquee</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index d7a3be3..9e19c57 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -170,6 +170,7 @@
<item name="starStyle">@android:style/Widget.CompoundButton.Star</item>
<item name="tabWidgetStyle">@android:style/Widget.TabWidget</item>
<item name="textViewStyle">@android:style/Widget.TextView</item>
+ <item name="webTextViewStyle">@android:style/Widget.WebTextView</item>
<item name="webViewStyle">@android:style/Widget.WebView</item>
<item name="dropDownItemStyle">@android:style/Widget.DropDownItem</item>
<item name="spinnerDropDownItemStyle">@android:style/Widget.DropDownItem.Spinner</item>
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 70c27c2..32c5c23 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -87,10 +87,11 @@
/**
* @hide Broadcast intent when the volume for a particular stream type changes.
- * Includes the stream and the new volume
+ * Includes the stream, the new volume and previous volumes
*
* @see #EXTRA_VOLUME_STREAM_TYPE
* @see #EXTRA_VOLUME_STREAM_VALUE
+ * @see #EXTRA_PREV_VOLUME_STREAM_VALUE
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
@@ -126,6 +127,12 @@
public static final String EXTRA_VOLUME_STREAM_VALUE =
"android.media.EXTRA_VOLUME_STREAM_VALUE";
+ /**
+ * @hide The previous volume associated with the stream for the volume changed intent.
+ */
+ public static final String EXTRA_PREV_VOLUME_STREAM_VALUE =
+ "android.media.EXTRA_PREV_VOLUME_STREAM_VALUE";
+
/** The audio stream for phone calls */
public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
/** The audio stream for system sounds */
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index bde8a47..668917e 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -403,30 +403,34 @@
// UI
mVolumePanel.postVolumeChanged(streamType, flags);
// Broadcast Intent
- sendVolumeUpdate(streamType);
+ sendVolumeUpdate(streamType, oldIndex, streamState.mIndex);
}
/** @see AudioManager#setStreamVolume(int, int, int) */
public void setStreamVolume(int streamType, int index, int flags) {
ensureValidStreamType(streamType);
+
+ final int oldIndex = mStreamStates[STREAM_VOLUME_ALIAS[streamType]].mIndex;
+
index = rescaleIndex(index * 10, streamType, STREAM_VOLUME_ALIAS[streamType]);
setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true);
// UI, etc.
mVolumePanel.postVolumeChanged(streamType, flags);
// Broadcast Intent
- sendVolumeUpdate(streamType);
+ sendVolumeUpdate(streamType, oldIndex, index);
}
- private void sendVolumeUpdate(int streamType) {
+ private void sendVolumeUpdate(int streamType, int oldIndex, int index) {
+ oldIndex = (oldIndex + 5) / 10;
+ index = (index + 5) / 10;
+
Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
- intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, getStreamVolume(streamType));
+ intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
+ intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
- // Currently, sending the intent only when the stream is BLUETOOTH_SCO
- if (streamType == AudioSystem.STREAM_BLUETOOTH_SCO) {
- mContext.sendBroadcast(intent);
- }
+ mContext.sendBroadcast(intent);
}
/**
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 2a65b0d..2012b3d 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -296,7 +296,7 @@
void SoundPool::autoPause()
{
- LOGV("pauseAll()");
+ LOGV("autoPause()");
Mutex::Autolock lock(&mLock);
for (int i = 0; i < mMaxChannels; ++i) {
SoundChannel* channel = &mChannelPool[i];
@@ -316,7 +316,7 @@
void SoundPool::autoResume()
{
- LOGV("pauseAll()");
+ LOGV("autoResume()");
Mutex::Autolock lock(&mLock);
for (int i = 0; i < mMaxChannels; ++i) {
SoundChannel* channel = &mChannelPool[i];
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index c92b9d7..dd0d064 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -7,8 +7,9 @@
android:process="system"
android:backupAgent="SettingsBackupAgent"
android:killAfterRestore="false"
- android:icon="@drawable/ic_launcher_settings"
- android:neverEncrypt="true">
+ android:icon="@drawable/ic_launcher_settings">
+
+ <!-- todo add: android:neverEncrypt="true" -->
<provider android:name="SettingsProvider" android:authorities="settings"
android:multiprocess="false"
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 0a6c72e..a267e0f 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -24,7 +24,7 @@
import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
-import android.app.DeviceAdmin;
+import android.app.DeviceAdminReceiver;
import android.app.DeviceAdminInfo;
import android.app.DevicePolicyManager;
import android.app.IDevicePolicyManager;
@@ -216,7 +216,7 @@
ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
if (admin != null) {
sendAdminCommandLocked(admin,
- DeviceAdmin.ACTION_DEVICE_ADMIN_DISABLED);
+ DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED);
// XXX need to wait for it to complete.
mAdminList.remove(admin);
mAdminMap.remove(adminReceiver);
@@ -393,7 +393,7 @@
mAdminList.add(admin);
saveSettingsLocked();
sendAdminCommandLocked(admin,
- DeviceAdmin.ACTION_DEVICE_ADMIN_ENABLED);
+ DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -709,7 +709,7 @@
}
return;
}
- Intent intent = new Intent(DeviceAdmin.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
+ Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
intent.setComponent(admin.info.getComponent());
mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
@Override
@@ -738,7 +738,7 @@
mFailedPasswordAttempts = 0;
saveSettingsLocked();
}
- sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_CHANGED,
+ sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -760,7 +760,7 @@
if (max > 0 && mFailedPasswordAttempts >= max) {
wipeDataLocked(0);
}
- sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_FAILED,
+ sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -778,7 +778,7 @@
try {
mFailedPasswordAttempts = 0;
saveSettingsLocked();
- sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_SUCCEEDED,
+ sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index d28047500..f0bab81 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -18,10 +18,12 @@
import android.app.Activity;
import android.app.ActivityManagerNative;
+import android.app.AlarmManager;
import android.app.IActivityManager;
import android.app.IUiModeManager;
import android.app.KeyguardManager;
import android.app.StatusBarManager;
+import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ActivityNotFoundException;
@@ -29,11 +31,18 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Configuration;
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.LocationProvider;
import android.os.Binder;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
@@ -42,6 +51,8 @@
import android.os.UEventObserver;
import android.provider.Settings;
import android.server.BluetoothService;
+import android.text.format.DateUtils;
+import android.text.format.Time;
import android.util.Log;
import com.android.internal.widget.LockPatternUtils;
@@ -59,10 +70,26 @@
private static final String DOCK_UEVENT_MATCH = "DEVPATH=/devices/virtual/switch/dock";
private static final String DOCK_STATE_PATH = "/sys/class/switch/dock/state";
+ private static final String KEY_LAST_UPDATE_INTERVAL = "LAST_UPDATE_INTERVAL";
+
+ private static final int MSG_DOCK_STATE = 0;
+ private static final int MSG_UPDATE_TWILIGHT = 1;
+ private static final int MSG_ENABLE_LOCATION_UPDATES = 2;
+
public static final int MODE_NIGHT_AUTO = Configuration.UI_MODE_NIGHT_MASK >> 4;
public static final int MODE_NIGHT_NO = Configuration.UI_MODE_NIGHT_NO >> 4;
public static final int MODE_NIGHT_YES = Configuration.UI_MODE_NIGHT_YES >> 4;
+ private static final long LOCATION_UPDATE_MS = 30 * DateUtils.MINUTE_IN_MILLIS;
+ private static final float LOCATION_UPDATE_DISTANCE_METER = 1000 * 20;
+ private static final long LOCATION_UPDATE_ENABLE_INTERVAL_MIN = 5000;
+ private static final long LOCATION_UPDATE_ENABLE_INTERVAL_MAX = 5 * DateUtils.MINUTE_IN_MILLIS;
+ // velocity for estimating a potential movement: 150km/h
+ private static final float MAX_VELOCITY_M_MS = 150 / 3600;
+ private static final double FACTOR_GMT_OFFSET_LONGITUDE = 1000.0 * 360.0 / DateUtils.DAY_IN_MILLIS;
+
+ private static final String ACTION_UPDATE_NIGHT_MODE = "com.android.server.action.UPDATE_NIGHT_MODE";
+
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mPreviousDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@@ -79,7 +106,11 @@
private boolean mKeyguardDisabled;
private LockPatternUtils mLockPatternUtils;
- private StatusBarManager mStatusBarManager;
+ private AlarmManager mAlarmManager;
+
+ private LocationManager mLocationManager;
+ private Location mLocation;
+ private StatusBarManager mStatusBarManager;
// The broadcast receiver which receives the result of the ordered broadcast sent when
// the dock state changes. The original ordered broadcast is sent with an initial result
@@ -115,6 +146,81 @@
}
};
+ private final BroadcastReceiver mTwilightUpdateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mCarModeEnabled && mNightMode == MODE_NIGHT_AUTO) {
+ mHandler.sendEmptyMessage(MSG_UPDATE_TWILIGHT);
+ }
+ }
+ };
+
+ private final LocationListener mLocationListener = new LocationListener() {
+
+ public void onLocationChanged(Location location) {
+ updateLocation(location);
+ }
+
+ public void onProviderDisabled(String provider) {
+ }
+
+ public void onProviderEnabled(String provider) {
+ }
+
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ // If the network location is no longer available check for a GPS fix
+ // and try to update the location.
+ if (provider == LocationManager.NETWORK_PROVIDER &&
+ status != LocationProvider.AVAILABLE) {
+ updateLocation(mLocation);
+ }
+ }
+
+ private void updateLocation(Location location) {
+ location = DockObserver.chooseBestLocation(location,
+ mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
+ if (hasMoved(location)) {
+ synchronized (this) {
+ mLocation = location;
+ }
+ if (mCarModeEnabled && mNightMode == MODE_NIGHT_AUTO) {
+ mHandler.sendEmptyMessage(MSG_UPDATE_TWILIGHT);
+ }
+ }
+ }
+
+ /*
+ * The user has moved if the accuracy circles of the two locations
+ * don't overlap.
+ */
+ private boolean hasMoved(Location location) {
+ if (location == null) {
+ return false;
+ }
+ if (mLocation == null) {
+ return true;
+ }
+
+ /* if new location is older than the current one, the devices hasn't
+ * moved.
+ */
+ if (location.getTime() < mLocation.getTime()) {
+ return false;
+ }
+
+ /* Get the distance between the two points */
+ float distance = mLocation.distanceTo(location);
+
+ /* Get the total accuracy radius for both locations */
+ float totalAccuracy = mLocation.getAccuracy() + location.getAccuracy();
+
+ /* If the distance is greater than the combined accuracy of the two
+ * points then they can't overlap and hence the user has moved.
+ */
+ return distance > totalAccuracy;
+ }
+ };
+
public DockObserver(Context context, PowerManagerService pm) {
mContext = context;
mPowerManager = pm;
@@ -123,6 +229,13 @@
ServiceManager.addService("uimode", mBinder);
+ mAlarmManager =
+ (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+ mLocationManager =
+ (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
+ mContext.registerReceiver(mTwilightUpdateReceiver,
+ new IntentFilter(ACTION_UPDATE_NIGHT_MODE));
+
startObserving(DOCK_UEVENT_MATCH);
}
@@ -190,83 +303,161 @@
update();
}
mSystemReady = true;
+ mHandler.sendEmptyMessage(MSG_ENABLE_LOCATION_UPDATES);
}
}
private final void update() {
- mHandler.sendEmptyMessage(0);
+ mHandler.sendEmptyMessage(MSG_DOCK_STATE);
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- synchronized (this) {
- Log.i(TAG, "Dock state changed: " + mDockState);
+ switch (msg.what) {
+ case MSG_DOCK_STATE:
+ synchronized (this) {
+ Log.i(TAG, "Dock state changed: " + mDockState);
- final ContentResolver cr = mContext.getContentResolver();
+ final ContentResolver cr = mContext.getContentResolver();
- if (Settings.Secure.getInt(cr,
- Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
- Log.i(TAG, "Device not provisioned, skipping dock broadcast");
- return;
- }
- // Pack up the values and broadcast them to everyone
- Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- if (mCarModeEnabled && mDockState != Intent.EXTRA_DOCK_STATE_CAR) {
- // Pretend to be in DOCK_STATE_CAR.
- intent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_CAR);
- } else {
- intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
- }
- intent.putExtra(Intent.EXTRA_CAR_MODE_ENABLED, mCarModeEnabled);
-
- // Check if this is Bluetooth Dock
- String address = BluetoothService.readDockBluetoothAddress();
- if (address != null)
- intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
- BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
-
- // User feedback to confirm dock connection. Particularly
- // useful for flaky contact pins...
- if (Settings.System.getInt(cr,
- Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1)
- {
- String whichSound = null;
- if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) {
- whichSound = Settings.System.DESK_UNDOCK_SOUND;
- } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
- whichSound = Settings.System.CAR_UNDOCK_SOUND;
+ if (Settings.Secure.getInt(cr,
+ Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
+ Log.i(TAG, "Device not provisioned, skipping dock broadcast");
+ return;
}
- } else {
- if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
- whichSound = Settings.System.DESK_DOCK_SOUND;
- } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
- whichSound = Settings.System.CAR_DOCK_SOUND;
+ // Pack up the values and broadcast them to everyone
+ Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ if (mCarModeEnabled && mDockState != Intent.EXTRA_DOCK_STATE_CAR) {
+ // Pretend to be in DOCK_STATE_CAR.
+ intent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_CAR);
+ } else {
+ intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
}
+ intent.putExtra(Intent.EXTRA_CAR_MODE_ENABLED, mCarModeEnabled);
+
+ // Check if this is Bluetooth Dock
+ String address = BluetoothService.readDockBluetoothAddress();
+ if (address != null)
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
+ BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
+
+ // User feedback to confirm dock connection. Particularly
+ // useful for flaky contact pins...
+ if (Settings.System.getInt(cr,
+ Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1)
+ {
+ String whichSound = null;
+ if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+ if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+ whichSound = Settings.System.DESK_UNDOCK_SOUND;
+ } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+ whichSound = Settings.System.CAR_UNDOCK_SOUND;
+ }
+ } else {
+ if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+ whichSound = Settings.System.DESK_DOCK_SOUND;
+ } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+ whichSound = Settings.System.CAR_DOCK_SOUND;
+ }
+ }
+
+ if (whichSound != null) {
+ final String soundPath = Settings.System.getString(cr, whichSound);
+ if (soundPath != null) {
+ final Uri soundUri = Uri.parse("file://" + soundPath);
+ if (soundUri != null) {
+ final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+ if (sfx != null) sfx.play();
+ }
+ }
+ }
+ }
+
+ // Send the ordered broadcast; the result receiver will receive after all
+ // broadcasts have been sent. If any broadcast receiver changes the result
+ // code from the initial value of RESULT_OK, then the result receiver will
+ // not launch the corresponding dock application. This gives apps a chance
+ // to override the behavior and stay in their app even when the device is
+ // placed into a dock.
+ mContext.sendStickyOrderedBroadcast(
+ intent, mResultReceiver, null, Activity.RESULT_OK, null, null);
+
}
-
- if (whichSound != null) {
- final String soundPath = Settings.System.getString(cr, whichSound);
- if (soundPath != null) {
- final Uri soundUri = Uri.parse("file://" + soundPath);
- if (soundUri != null) {
- final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
- if (sfx != null) sfx.play();
+ break;
+ case MSG_UPDATE_TWILIGHT:
+ synchronized (this) {
+ if (mCarModeEnabled && mLocation != null && mNightMode == MODE_NIGHT_AUTO) {
+ try {
+ DockObserver.this.updateTwilight();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to change night mode.", e);
}
}
}
- }
+ break;
+ case MSG_ENABLE_LOCATION_UPDATES:
+ if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
+ mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
+ LOCATION_UPDATE_MS, LOCATION_UPDATE_DISTANCE_METER, mLocationListener);
+ retrieveLocation();
+ if (mLocation != null) {
+ try {
+ DockObserver.this.updateTwilight();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to change night mode.", e);
+ }
+ }
+ } else {
+ long interval = msg.getData().getLong(KEY_LAST_UPDATE_INTERVAL);
+ interval *= 1.5;
+ if (interval == 0) {
+ interval = LOCATION_UPDATE_ENABLE_INTERVAL_MIN;
+ } else if (interval > LOCATION_UPDATE_ENABLE_INTERVAL_MAX) {
+ interval = LOCATION_UPDATE_ENABLE_INTERVAL_MAX;
+ }
+ Bundle bundle = new Bundle();
+ bundle.putLong(KEY_LAST_UPDATE_INTERVAL, interval);
+ Message newMsg = mHandler.obtainMessage(MSG_ENABLE_LOCATION_UPDATES);
+ newMsg.setData(bundle);
+ mHandler.sendMessageDelayed(newMsg, interval);
+ }
+ break;
+ }
+ }
- // Send the ordered broadcast; the result receiver will receive after all
- // broadcasts have been sent. If any broadcast receiver changes the result
- // code from the initial value of RESULT_OK, then the result receiver will
- // not launch the corresponding dock application. This gives apps a chance
- // to override the behavior and stay in their app even when the device is
- // placed into a dock.
- mContext.sendStickyOrderedBroadcast(
- intent, mResultReceiver, null, Activity.RESULT_OK, null, null);
+ private void retrieveLocation() {
+ final Location gpsLocation =
+ mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ Location location;
+ Criteria criteria = new Criteria();
+ criteria.setSpeedRequired(false);
+ criteria.setAltitudeRequired(false);
+ criteria.setBearingRequired(false);
+ final String bestProvider = mLocationManager.getBestProvider(criteria, true);
+ if (LocationManager.GPS_PROVIDER.equals(bestProvider)) {
+ location = gpsLocation;
+ } else {
+ location = DockObserver.chooseBestLocation(gpsLocation,
+ mLocationManager.getLastKnownLocation(bestProvider));
+ }
+ // In the case there is no location available (e.g. GPS fix or network location
+ // is not available yet), the longitude of the location is estimated using the timezone,
+ // latitude and accuracy are set to get a good average.
+ if (location == null) {
+ Time currentTime = new Time();
+ currentTime.set(System.currentTimeMillis());
+ double lngOffset = FACTOR_GMT_OFFSET_LONGITUDE * currentTime.gmtoff
+ - (currentTime.isDst > 0 ? 3600 : 0);
+ location = new Location("fake");
+ location.setLongitude(lngOffset);
+ location.setLatitude(59.95);
+ location.setAccuracy(417000.0f);
+ location.setTime(System.currentTimeMillis());
+ }
+ synchronized (this) {
+ mLocation = location;
}
}
};
@@ -274,10 +465,15 @@
private void setCarMode(boolean enabled) throws RemoteException {
mCarModeEnabled = enabled;
if (enabled) {
- setMode(Configuration.UI_MODE_TYPE_CAR, mNightMode);
+ if (mNightMode == MODE_NIGHT_AUTO) {
+ updateTwilight();
+ } else {
+ setMode(Configuration.UI_MODE_TYPE_CAR, mNightMode << 4);
+ }
} else {
// Disabling the car mode clears the night mode.
- setMode(Configuration.UI_MODE_TYPE_NORMAL, MODE_NIGHT_NO);
+ setMode(Configuration.UI_MODE_TYPE_NORMAL,
+ Configuration.UI_MODE_NIGHT_UNDEFINED);
}
if (mStatusBarManager == null) {
@@ -290,38 +486,112 @@
// the status bar should be totally disabled, the calls below will
// have no effect until the device is unlocked.
if (mStatusBarManager != null) {
- mStatusBarManager.disable(enabled
+ mStatusBarManager.disable(enabled
? StatusBarManager.DISABLE_NOTIFICATION_TICKER
: StatusBarManager.DISABLE_NONE);
}
}
private void setMode(int modeType, int modeNight) throws RemoteException {
+ long ident = Binder.clearCallingIdentity();
final IActivityManager am = ActivityManagerNative.getDefault();
Configuration config = am.getConfiguration();
-
if (config.uiMode != (modeType | modeNight)) {
config.uiMode = modeType | modeNight;
- long ident = Binder.clearCallingIdentity();
am.updateConfiguration(config);
- Binder.restoreCallingIdentity(ident);
}
+ Binder.restoreCallingIdentity(ident);
}
private void setNightMode(int mode) throws RemoteException {
- mNightMode = mode;
- switch (mode) {
- case MODE_NIGHT_NO:
- case MODE_NIGHT_YES:
- setMode(Configuration.UI_MODE_TYPE_CAR, mode << 4);
- break;
- case MODE_NIGHT_AUTO:
- // FIXME: not yet supported, this functionality will be
- // added in a separate change.
- break;
- default:
- setMode(Configuration.UI_MODE_TYPE_CAR, MODE_NIGHT_NO << 4);
- break;
+ if (mNightMode != mode) {
+ mNightMode = mode;
+ switch (mode) {
+ case MODE_NIGHT_NO:
+ case MODE_NIGHT_YES:
+ setMode(Configuration.UI_MODE_TYPE_CAR, mode << 4);
+ break;
+ case MODE_NIGHT_AUTO:
+ long ident = Binder.clearCallingIdentity();
+ updateTwilight();
+ Binder.restoreCallingIdentity(ident);
+ break;
+ default:
+ setMode(Configuration.UI_MODE_TYPE_CAR, MODE_NIGHT_NO << 4);
+ break;
+ }
+ }
+ }
+
+ private void updateTwilight() throws RemoteException {
+ synchronized (this) {
+ if (mLocation == null) {
+ return;
+ }
+ final long currentTime = System.currentTimeMillis();
+ int nightMode;
+ // calculate current twilight
+ TwilightCalculator tw = new TwilightCalculator();
+ tw.calculateTwilight(currentTime,
+ mLocation.getLatitude(), mLocation.getLongitude());
+ if (tw.mState == TwilightCalculator.DAY) {
+ nightMode = MODE_NIGHT_NO;
+ } else {
+ nightMode = MODE_NIGHT_YES;
+ }
+
+ // schedule next update
+ final int mLastTwilightState = tw.mState;
+ // add some extra time to be on the save side.
+ long nextUpdate = DateUtils.MINUTE_IN_MILLIS;
+ if (currentTime > tw.mSunset) {
+ // next update should be on the following day
+ tw.calculateTwilight(currentTime
+ + DateUtils.DAY_IN_MILLIS, mLocation.getLatitude(),
+ mLocation.getLongitude());
+ }
+
+ if (mLastTwilightState == TwilightCalculator.NIGHT) {
+ nextUpdate += tw.mSunrise;
+ } else {
+ nextUpdate += tw.mSunset;
+ }
+
+ Intent updateIntent = new Intent(ACTION_UPDATE_NIGHT_MODE);
+ PendingIntent pendingIntent =
+ PendingIntent.getBroadcast(mContext, 0, updateIntent, 0);
+ mAlarmManager.cancel(pendingIntent);
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP, nextUpdate, pendingIntent);
+
+ // set current mode
+ setMode(Configuration.UI_MODE_TYPE_CAR, nightMode << 4);
+ }
+ }
+
+ /**
+ * Check which of two locations is better by comparing the distance a device
+ * could have cover since the last timestamp of the location.
+ *
+ * @param location first location
+ * @param otherLocation second location
+ * @return one of the two locations
+ */
+ protected static Location chooseBestLocation(Location location, Location otherLocation) {
+ if (location == null) {
+ return otherLocation;
+ }
+ if (otherLocation == null) {
+ return location;
+ }
+ final long currentTime = System.currentTimeMillis();
+ float gpsPotentialMove = MAX_VELOCITY_M_MS * (currentTime - location.getTime())
+ + location.getAccuracy();
+ float otherPotentialMove = MAX_VELOCITY_M_MS * (currentTime - otherLocation.getTime())
+ + otherLocation.getAccuracy();
+ if (gpsPotentialMove < otherPotentialMove) {
+ return location;
+ } else {
+ return otherLocation;
}
}
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index cf083c04..ceae973 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -259,8 +259,12 @@
rdata[idx++] = line.substring(tok[0].length() + 1);
} else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
if (LOCAL_LOGD) Log.d(TAG, String.format("List terminated with {%s}", line));
- if (i != rsp.size()) {
- Log.w(TAG, String.format("Recv'd %d lines after list term", (rsp.size()-i)));
+ int last = rsp.size() -1;
+ if (i != last) {
+ Log.w(TAG, String.format("Recv'd %d lines after end of list {%s}", (last-i), cmd));
+ for (int j = i; j <= last ; j++) {
+ Log.w(TAG, String.format("ExtraData <%s>", rsp.get(i)));
+ }
}
return rdata;
} else {
diff --git a/services/java/com/android/server/TwilightCalculator.java b/services/java/com/android/server/TwilightCalculator.java
new file mode 100644
index 0000000..a8f67d8
--- /dev/null
+++ b/services/java/com/android/server/TwilightCalculator.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.text.format.DateUtils;
+import android.util.FloatMath;
+
+/** @hide */
+public class TwilightCalculator {
+
+ /** Value of {@link #mState} if it is currently day */
+ public static final int DAY = 0;
+
+ /** Value of {@link #mState} if it is currently night */
+ public static final int NIGHT = 1;
+
+ private static final float DEGREES_TO_RADIANS = (float) (Math.PI / 180.0f);
+
+ // element for calculating solar transit.
+ private static final float J0 = 0.0009f;
+
+ // correction for civil twilight
+ private static final float ALTIDUTE_CORRECTION_CIVIL_TWILIGHT = -0.104719755f;
+
+ // coefficients for calculating Equation of Center.
+ private static final float C1 = 0.0334196f;
+ private static final float C2 = 0.000349066f;
+ private static final float C3 = 0.000005236f;
+
+ private static final float OBLIQUITY = 0.40927971f;
+
+ // Java time on Jan 1, 2000 12:00 UTC.
+ private static final long UTC_2000 = 946728000000L;
+
+ /** Time of sunset (civil twilight) in milliseconds. */
+ public long mSunset;
+
+ /** Time of sunrise (civil twilight) in milliseconds. */
+ public long mSunrise;
+
+ /** Current state */
+ public int mState;
+
+ /**
+ * calculates the civil twilight bases on time and geo-coordinates.
+ *
+ * @param time time in milliseconds.
+ * @param latiude latitude in degrees.
+ * @param longitude latitude in degrees.
+ */
+ public void calculateTwilight(long time, double latiude, double longitude) {
+ final float daysSince2000 = (float) (time - UTC_2000) / DateUtils.DAY_IN_MILLIS;
+
+ // mean anomaly
+ final float meanAnomaly = 6.240059968f + daysSince2000 * 0.01720197f;
+
+ // true anomaly
+ final float trueAnomaly = meanAnomaly + C1 * FloatMath.sin(meanAnomaly) + C2
+ * FloatMath.sin(2 * meanAnomaly) + C3 * FloatMath.sin(3 * meanAnomaly);
+
+ // ecliptic longitude
+ final float solarLng = trueAnomaly + 1.796593063f + (float) Math.PI;
+
+ // solar transit in days since 2000
+ final double arcLongitude = -longitude / 360;
+ float n = Math.round(daysSince2000 - J0 - arcLongitude);
+ double solarTransitJ2000 = n + J0 + arcLongitude + 0.0053f * FloatMath.sin(meanAnomaly)
+ + -0.0069f * FloatMath.sin(2 * solarLng);
+
+ // declination of sun
+ double solarDec = Math.asin(FloatMath.sin(solarLng) * FloatMath.sin(OBLIQUITY));
+
+ final double latRad = latiude * DEGREES_TO_RADIANS;
+ float hourAngle = (float) (Math
+ .acos((FloatMath.sin(ALTIDUTE_CORRECTION_CIVIL_TWILIGHT) - Math.sin(latRad)
+ * Math.sin(solarDec))
+ / (Math.cos(latRad) * Math.cos(solarDec))) / (2 * Math.PI));
+
+ mSunset = Math.round((solarTransitJ2000 + hourAngle) * DateUtils.DAY_IN_MILLIS) + UTC_2000;
+ mSunrise = Math.round((solarTransitJ2000 - hourAngle) * DateUtils.DAY_IN_MILLIS) + UTC_2000;
+
+ if (mSunrise < time && mSunset > time) {
+ mState = DAY;
+ } else {
+ mState = NIGHT;
+ }
+ }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
index 9caae3d..41e527c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
@@ -409,7 +409,7 @@
case USIM_EFIAP_TAG:
case USIM_EFSNE_TAG:
data = tlv.getData();
- int efid = data[0] << 8 | data[1];
+ int efid = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
val.put(tag, efid);
break;
}
diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml
index 2b6b81e..28f1e73 100644
--- a/tests/AndroidTests/AndroidManifest.xml
+++ b/tests/AndroidTests/AndroidManifest.xml
@@ -29,6 +29,11 @@
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
+ <uses-permission android:name="android.permission.ASEC_ACCESS" />
+ <uses-permission android:name="android.permission.ASEC_CREATE" />
+ <uses-permission android:name="android.permission.ASEC_DESTROY" />
+ <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT" />
+ <uses-permission android:name="android.permission.ASEC_RENAME" />
<uses-permission android:name="com.android.unit_tests.permission.TEST_GRANTED" />
<uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" />
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
diff --git a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
new file mode 100755
index 0000000..7569d7a
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.unit_tests;
+
+import android.os.storage.IMountService.Stub;
+
+import android.net.Uri;
+import android.os.FileUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.storage.IMountService;
+import android.os.storage.StorageResultCode;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.StatFs;
+import android.provider.Settings;
+import junit.framework.Assert;
+
+public class AsecTests extends AndroidTestCase {
+ private static final boolean localLOGV = true;
+ public static final String TAG="AsecTests";
+
+ void failStr(String errMsg) {
+ Log.w(TAG, "errMsg="+errMsg);
+ }
+ void failStr(Exception e) {
+ Log.w(TAG, "e.getMessage="+e.getMessage());
+ Log.w(TAG, "e="+e);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (localLOGV) Log.i(TAG, "Cleaning out old test containers");
+ cleanupContainers();
+ }
+
+ private void cleanupContainers() throws RemoteException {
+ IMountService ms = getMs();
+ String[] containers = ms.getSecureContainerList();
+
+ for (int i = 0; i < containers.length; i++) {
+ if (containers[i].startsWith("com.android.unittests.AsecTests.")) {
+ ms.destroySecureContainer(containers[i]);
+ }
+ }
+ }
+
+ private IMountService getMs() {
+ IBinder service = ServiceManager.getService("mount");
+ if (service != null) {
+ return IMountService.Stub.asInterface(service);
+ } else {
+ Log.e(TAG, "Can't get mount service");
+ }
+ return null;
+ }
+
+ private boolean isMediaMounted() {
+ try {
+ String mPath = Environment.getExternalStorageDirectory().toString();
+ String state = getMs().getVolumeState(mPath);
+ return Environment.MEDIA_MOUNTED.equals(state);
+ } catch (RemoteException e) {
+ failStr(e);
+ return false;
+ }
+ }
+
+ public void testCreateContainer() {
+ Assert.assertTrue(isMediaMounted());
+ IMountService ms = getMs();
+ try {
+ int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateContainer", 4, "fat", "none", 1000);
+ Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+ } catch (Exception e) {
+ failStr(e);
+ }
+ }
+
+ public void testDestroyContainer() {
+ Assert.assertTrue(isMediaMounted());
+ IMountService ms = getMs();
+ try {
+ int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testDestroyContainer", 4, "fat", "none", 1000);
+ Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+ rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testDestroyContainer");
+ Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+ } catch (Exception e) {
+ failStr(e);
+ }
+ }
+
+ public void testMountContainer() {
+ Assert.assertTrue(isMediaMounted());
+ IMountService ms = getMs();
+ try {
+ int rc = ms.createSecureContainer(
+ "com.android.unittests.AsecTests.testMountContainer", 4, "fat", "none", 1000);
+ Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+
+ rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountContainer");
+ Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+
+ rc = ms.mountSecureContainer("com.android.unittests.AsecTests.testMountContainer", "none", 1000);
+ Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+ } catch (Exception e) {
+ failStr(e);
+ }
+ }
+
+ public void testMountBadKey() {
+ Assert.assertTrue(isMediaMounted());
+ IMountService ms = getMs();
+ try {
+ int rc = ms.createSecureContainer(
+ "com.android.unittests.AsecTests.testMountBadKey", 4, "fat",
+ "00000000000000000000000000000000", 1000);
+ Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+
+ rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountBadKey");
+ Assert.assertEquals(StorageResultCode.OperationSucceeded, rc);
+
+ rc = ms.mountSecureContainer(
+ "com.android.unittests.AsecTests.testMountBadKey",
+ "00000000000000000000000000000001", 1001);
+ Assert.assertEquals(StorageResultCode.OperationFailedInternalError, rc);
+
+ rc = ms.mountSecureContainer(
+ "com.android.unittests.AsecTests.testMountBadKey", "none", 1001);
+ Assert.assertEquals(StorageResultCode.OperationFailedInternalError, rc);
+ } catch (Exception e) {
+ failStr(e);
+ }
+ }
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 452368e..4d51356 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -81,172 +81,112 @@
"platform", // platform specific
"http/wml",
};
-
+
static final String [] ignoreTestList = {
- // RegExp is exponatal
- "fast/regex/test1.html",
- "fast/regex/slow.html",
- // RegExp is too large, causing OOM
- "fast/js/regexp-charclass-crash.html",
- // The Android browser has no notion of private browsing.
- "storage/private-browsing-readonly.html",
- "storage/domstorage/localstorage/private-browsing-affects-storage.html",
- "storage/domstorage/sessionstorage/private-browsing-affects-storage.html",
- // Android layout tests are stored in "layout_tests". The following two
- // tests expect "LayoutTests" in their output.
- "storage/domstorage/localstorage/iframe-events.html",
- "storage/domstorage/sessionstorage/iframe-events.html",
- // We do not support multi touch events.
- "fast/events/touch/basic-multi-touch-events.html",
- // below tests (failed or crashes) are filtered out temporarily due to prioritizing
"editing/selection/move-left-right.html",
+ "fast/events/touch/basic-multi-touch-events.html", // We do not support multi touch events.
+ "fast/js/regexp-charclass-crash.html", // RegExp is too large, causing OOM
+ "fast/regex/test1.html", // RegExp is exponential
+ "fast/regex/slow.html", // RegExp is exponential
+ "storage/domstorage/localstorage/iframe-events.html", // Expects test to be in LayoutTests
+ "storage/domstorage/localstorage/private-browsing-affects-storage.html", // No notion of private browsing.
+ "storage/domstorage/sessionstorage/iframe-events.html", // Expects test to be in LayoutTests
+ "storage/domstorage/sessionstorage/private-browsing-affects-storage.html", // No notion of private browsing.
+ "storage/private-browsing-readonly.html", // No notion of private browsing.
};
-
+
static void fillIgnoreResultSet() {
- // need test plugin
- ignoreResultList.add("fast/dom/Window/Plug-ins.html");
- // pixel depth
- ignoreResultList.add("fast/dom/Window/window-screen-properties.html");
- // missing space in textrun, ok as text is wrapped. ignore. #714933
- ignoreResultList.add("fast/events/onload-webkit-before-webcore.html");
- // missing support for textInputController.makeAttributedString()
- ignoreResultList.add("fast/forms/attributed-strings.html");
- // charset convert. #516936 ignore, won't fix
- ignoreResultList.add("fast/forms/form-data-encoding-2.html");
- // charset convert. #516936 ignore, won't fix
- ignoreResultList.add("fast/forms/form-data-encoding.html");
- // execCommand "insertText" not supported
- ignoreResultList.add("fast/forms/input-appearance-maxlength.html");
- // Copy&Paste commands not supported
- ignoreResultList.add("fast/forms/input-truncate-newline.html");
- ignoreResultList.add("fast/forms/textarea-paste-newline.html");
- // requires eventSender.mouseMoveTo, mouseDown & mouseUp and
- // abs. position of mouse to select a word. ignore, won't fix #716583
- ignoreResultList.add("fast/forms/onselect-textarea.html");
- // requires eventSender.mouseMoveTo, mouseDown & mouseUp and
- // abs. position of mouse to select a word. ignore, won't fix #716583
- ignoreResultList.add("fast/forms/onselect-textfield.html");
- // not implemented queryCommandEnabled:BackColor, Undo & Redo
- ignoreResultList.add("fast/forms/plaintext-mode-1.html");
- // Our text areas are a little thinner than Apples. Also RTL test failes
- ignoreResultList.add("fast/forms/textarea-appearance-wrap.html");
- // Our text areas are a little thinner than Apples
- ignoreResultList.add("fast/forms/textarea-hard-linewrap.html");
- // screen width&height are different
- ignoreResultList.add("fast/frames/frameElement-widthheight.html");
- ignoreResultList.add("fast/frames/frame-js-url-clientWidth.html");
- // requires JS test API, textInputController
- ignoreResultList.add("fast/text/attributed-substring-from-range.html");
- ignoreResultList.add("fast/text/attributed-substring-from-range-001.html");
- // will not fix #619707
- ignoreResultList.add("fast/css/case-transform.html");
- // different platform defaults for font and different screen size
- ignoreResultList.add("fast/css/computed-style.html");
- // different screen size result in extra spaces in Apple compared to us
- ignoreResultList.add("fast/dom/Element/offsetLeft-offsetTop-body-quirk.html");
- // xslt and xpath elements missing from property list
- ignoreResultList.add("fast/dom/Window/window-properties.html");
- // requires textInputController.characterIndexForPoint
- ignoreResultList.add("fast/dom/character-index-for-point.html");
- // requires xpath support
- ignoreResultList.add("fast/dom/gc-9.html");
- // requires xslt and xpath support
- ignoreResultList.add("fast/dom/global-constructors.html");
- // dynamic plugins not supported
- ignoreResultList.add("fast/dom/object-embed-plugin-scripting.html");
- ignoreResultList.add("fast/js/navigator-mimeTypes-length.html");
- // there is extra spacing in the file due to multiple input boxes
- // fitting on one line on Apple, ours are wrapped. Space at line ends
- // are stripped.
- ignoreResultList.add("fast/dom/tabindex-clamp.html");
-
- // requires eventSender.mouseDown(),mouseUp()
- ignoreResultList.add("fast/dom/Window/window-xy-properties.html");
- ignoreResultList.add("fast/events/window-events-bubble.html");
- ignoreResultList.add("fast/events/window-events-bubble2.html");
- ignoreResultList.add("fast/events/window-events-capture.html");
- ignoreResultList.add("fast/forms/select-empty-list.html");
- ignoreResultList.add("fast/replaced/image-map.html");
- ignoreResultList.add("fast/events/capture-on-target.html");
- ignoreResultList.add("fast/events/dblclick-addEventListener.html");
- ignoreResultList.add("fast/events/drag-in-frames.html");
- ignoreResultList.add("fast/events/drag-outside-window.html");
- ignoreResultList.add("fast/events/event-sender-mouse-click.html");
- ignoreResultList.add("fast/events/event-view-toString.html");
- ignoreResultList.add("fast/events/frame-click-focus.html");
- ignoreResultList.add("fast/events/input-image-scrolled-x-y.html");
- ignoreResultList.add("fast/events/anchor-image-scrolled-x-y.html");
- ignoreResultList.add("fast/events/mouseclick-target-and-positioning.html");
- ignoreResultList.add("fast/events/mouseover-mouseout.html");
- ignoreResultList.add("fast/events/mouseover-mouseout2.html");
- ignoreResultList.add("fast/events/mouseup-outside-button.html");
- ignoreResultList.add("fast/events/mouseup-outside-document.html");
- ignoreResultList.add("fast/events/onclick-list-marker.html");
- ignoreResultList.add("fast/events/ondragenter.html");
- ignoreResultList.add("fast/forms/drag-into-textarea.html");
- ignoreResultList.add("fast/forms/input-select-on-click.html");
- ignoreResultList.add("fast/forms/listbox-onchange.html");
- ignoreResultList.add("fast/forms/search-cancel-button-mouseup.html");
- ignoreResultList.add("fast/forms/textarea-scrolled-endline-caret.html");
-
- // there is extra spacing in the file due to multiple frame boxes
- // fitting on one line on Apple, ours are wrapped. Space at line ends
- // are stripped.
- ignoreResultList.add("fast/events/iframe-object-onload.html");
- // eventSender.mouseDown(), mouseUp() and objc API missing
- ignoreResultList.add("fast/events/mouseup-outside-document.html");
- ignoreResultList.add("fast/events/objc-keyboard-event-creation.html");
- ignoreResultList.add("fast/events/objc-event-api.html");
- // not capturing the console messages
- ignoreResultList.add("fast/forms/selected-index-assert.html");
- ignoreResultList.add("fast/parser/script-tag-with-trailing-slash.html");
- // there is extra spacing as the text areas and input boxes fit next
- // to each other on Apple, but are wrapped on our screen.
- ignoreResultList.add("fast/forms/selection-functions.html");
- // Text selection done differently on our platform. When a inputbox
- // gets focus, the entire block is selected.
- ignoreResultList.add("fast/forms/textarea-initial-caret-position.html");
- ignoreResultList.add("fast/forms/textarea-no-scroll-on-blur.html");
- // Requires LayoutTests to exist at /tmp/LayoutTests
- ignoreResultList.add("fast/loader/local-JavaScript-from-local.html");
- ignoreResultList.add("fast/loader/local-iFrame-source-from-local.html");
- // extra spacing because iFrames rendered next to each other on Apple
- ignoreResultList.add("fast/loader/opaque-base-url.html");
- ignoreResultList.add("fast/text/plain-text-line-breaks.html");
+ ignoreResultList.add("fast/css/case-transform.html"); // will not fix #619707
+ ignoreResultList.add("fast/css/computed-style.html"); // different platform defaults for font and different screen size
+ ignoreResultList.add("fast/dom/Element/offsetLeft-offsetTop-body-quirk.html"); // different screen size result in extra spaces in Apple compared to us
+ ignoreResultList.add("fast/dom/Window/Plug-ins.html"); // need test plugin
+ ignoreResultList.add("fast/dom/Window/window-properties.html"); // xslt and xpath elements missing from property list
+ ignoreResultList.add("fast/dom/Window/window-screen-properties.html"); // pixel depth
+ ignoreResultList.add("fast/dom/Window/window-xy-properties.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/dom/character-index-for-point.html"); // requires textInputController.characterIndexForPoint
+ ignoreResultList.add("fast/dom/gc-9.html"); // requires xpath support
+ ignoreResultList.add("fast/dom/global-constructors.html"); // requires xslt and xpath support
+ ignoreResultList.add("fast/dom/object-embed-plugin-scripting.html"); // dynamic plugins not supported
+ ignoreResultList.add("fast/dom/tabindex-clamp.html"); // there is extra spacing in the file due to multiple input boxes fitting on one line on Apple, ours are wrapped. Space at line ends are stripped.
+ ignoreResultList.add("fast/events/anchor-image-scrolled-x-y.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/capture-on-target.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/dblclick-addEventListener.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/drag-in-frames.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/drag-outside-window.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/event-sender-mouse-click.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/event-view-toString.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/frame-click-focus.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/iframe-object-onload.html"); // there is extra spacing in the file due to multiple frame boxes fitting on one line on Apple, ours are wrapped. Space at line ends are stripped.
+ ignoreResultList.add("fast/events/input-image-scrolled-x-y.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/mouseclick-target-and-positioning.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/mouseover-mouseout.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/mouseover-mouseout2.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/mouseup-outside-button.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/mouseup-outside-document.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/objc-event-api.html"); // eventSender.mouseDown(), mouseUp() and objc API missing
+ ignoreResultList.add("fast/events/objc-keyboard-event-creation.html"); // eventSender.mouseDown(), mouseUp() and objc API missing
+ ignoreResultList.add("fast/events/onclick-list-marker.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/ondragenter.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/onload-webkit-before-webcore.html"); // missing space in textrun, ok as text is wrapped. ignore. #714933
+ ignoreResultList.add("fast/events/window-events-bubble.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/window-events-bubble2.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/events/window-events-capture.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/forms/attributed-strings.html"); // missing support for textInputController.makeAttributedString()
+ ignoreResultList.add("fast/forms/drag-into-textarea.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/forms/form-data-encoding-2.html"); // charset convert. #516936 ignore, won't fix
+ ignoreResultList.add("fast/forms/form-data-encoding.html"); // charset convert. #516936 ignore, won't fix
+ ignoreResultList.add("fast/forms/input-appearance-maxlength.html"); // execCommand "insertText" not supported
+ ignoreResultList.add("fast/forms/input-select-on-click.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/forms/input-truncate-newline.html"); // Copy&Paste commands not supported
+ ignoreResultList.add("fast/forms/listbox-onchange.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/forms/onselect-textarea.html"); // requires eventSender.mouseMoveTo, mouseDown & mouseUp and abs. position of mouse to select a word. ignore, won't fix #716583
+ ignoreResultList.add("fast/forms/onselect-textfield.html"); // requires eventSender.mouseMoveTo, mouseDown & mouseUp and abs. position of mouse to select a word. ignore, won't fix #716583
+ ignoreResultList.add("fast/forms/plaintext-mode-1.html"); // not implemented queryCommandEnabled:BackColor, Undo & Redo
+ ignoreResultList.add("fast/forms/search-cancel-button-mouseup.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/forms/select-empty-list.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/forms/selected-index-assert.html"); // not capturing the console messages
+ ignoreResultList.add("fast/forms/selection-functions.html"); // there is extra spacing as the text areas and input boxes fit next to each other on Apple, but are wrapped on our screen.
+ ignoreResultList.add("fast/forms/textarea-appearance-wrap.html"); // Our text areas are a little thinner than Apples. Also RTL test failes
+ ignoreResultList.add("fast/forms/textarea-hard-linewrap.html"); // Our text areas are a little thinner than Apples
+ ignoreResultList.add("fast/forms/textarea-initial-caret-position.html"); // Text selection done differently on our platform. When a inputbox gets focus, the entire block is selected.
+ ignoreResultList.add("fast/forms/textarea-no-scroll-on-blur.html"); // Text selection done differently on our platform. When a inputbox gets focus, the entire block is selected.
+ ignoreResultList.add("fast/forms/textarea-paste-newline.html"); // Copy&Paste commands not supported
+ ignoreResultList.add("fast/forms/textarea-scrolled-endline-caret.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/frames/frameElement-widthheight.html"); // screen width&height are different
+ ignoreResultList.add("fast/frames/frame-js-url-clientWidth.html"); // screen width&height are different
+ ignoreResultList.add("fast/js/navigator-mimeTypes-length.html"); // dynamic plugins not supported
+ ignoreResultList.add("fast/loader/local-JavaScript-from-local.html"); // Requires LayoutTests to exist at /tmp/LayoutTests
+ ignoreResultList.add("fast/loader/local-iFrame-source-from-local.html"); // Requires LayoutTests to exist at /tmp/LayoutTests
+ ignoreResultList.add("fast/loader/opaque-base-url.html"); // extra spacing because iFrames rendered next to each other on Apple
+ ignoreResultList.add("fast/parser/script-tag-with-trailing-slash.html"); // not capturing the console messages
+ ignoreResultList.add("fast/replaced/image-map.html"); // requires eventSender.mouseDown(),mouseUp()
+ ignoreResultList.add("fast/text/attributed-substring-from-range.html"); // requires JS test API, textInputController
+ ignoreResultList.add("fast/text/attributed-substring-from-range-001.html"); // requires JS test API, textInputController
+ ignoreResultList.add("fast/text/plain-text-line-breaks.html"); // extra spacing because iFrames rendered next to each other on Apple
}
-
+
static void fillBugTable() {
- bugList.put("fast/forms/check-box-enter-key.html", "716715");
bugList.put("fast/forms/focus-control-to-page.html", "716638");
bugList.put("fast/html/tab-order.html", "719289");
bugList.put("fast/dom/attribute-namespaces-get-set.html", "733229");
- bugList.put("fast/dom/location-hash.html", "733822");
bugList.put("fast/dom/set-innerHTML.html", "733823");
bugList.put("fast/dom/xmlhttprequest-get.html", "733846");
bugList.put("fast/encoding/css-charset-default.html", "733856");
bugList.put("fast/encoding/default-xhtml-encoding.html", "733882");
bugList.put("fast/encoding/meta-in-xhtml.html", "733882");
bugList.put("fast/events/frame-tab-focus.html", "734308");
- bugList.put("fast/events/keydown-keypress-focus-change.html", "653224");
- bugList.put("fast/events/keypress-focus-change.html", "653224");
bugList.put("fast/events/option-tab.html", "734308");
bugList.put("fast/forms/focus2.html", "735111");
bugList.put("fast/forms/listbox-selection.html", "735116");
bugList.put("fast/forms/search-event-delay.html", "735120");
bugList.put("fast/frames/iframe-window-focus.html", "735140");
bugList.put("fast/innerHTML/004.html", "733882");
- bugList.put("fast/js/date-DST-time-cusps.html", "735144");
bugList.put("fast/js/string-capitalization.html", "516936");
bugList.put("fast/js/string-concatenate-outofmemory.html","735152");
bugList.put("fast/parser/external-entities.html", "735176");
- bugList.put("fast/events/div-focus.html", "735185");
bugList.put("fast/overflow/scroll-vertical-not-horizontal.html", "735196");
bugList.put("fast/events/arrow-navigation.html", "735233");
bugList.put("fast/forms/select-type-ahead-non-latin.html", "735244");
- bugList.put("fast/events/js-keyboard-event-creation.html", "735255");
-
}
-
-
-
+
}