Merge "add support for audio/3gpp"
diff --git a/api/current.xml b/api/current.xml
index e5177efa..444b002 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"
@@ -5971,6 +5960,17 @@
visibility="public"
>
</field>
+<field name="overscrollMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843450"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="padding"
type="int"
transient="false"
@@ -6855,7 +6855,7 @@
type="int"
transient="false"
volatile="false"
- value="16843449"
+ value="16843448"
static="true"
final="true"
deprecated="not deprecated"
@@ -9077,7 +9077,7 @@
type="int"
transient="false"
volatile="false"
- value="16843450"
+ value="16843449"
static="true"
final="true"
deprecated="not deprecated"
@@ -20067,242 +20067,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"
@@ -20547,6 +20311,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"
@@ -78725,6 +78725,17 @@
visibility="public"
>
</field>
+<field name="PASSIVE_PROVIDER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""passive""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="LocationProvider"
extends="java.lang.Object"
@@ -84485,6 +84496,28 @@
<parameter name="srcQuality" type="int">
</parameter>
</constructor>
+<method name="autoPause"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="autoResume"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="load"
return="int"
abstract="false"
@@ -84626,6 +84659,19 @@
<parameter name="loop" type="int">
</parameter>
</method>
+<method name="setOnLoadCompleteListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.SoundPool.OnLoadCompleteListener">
+</parameter>
+</method>
<method name="setPriority"
return="void"
abstract="false"
@@ -84700,6 +84746,31 @@
</parameter>
</method>
</class>
+<interface name="SoundPool.OnLoadCompleteListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onLoadComplete"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="soundPool" type="android.media.SoundPool">
+</parameter>
+<parameter name="sampleId" type="int">
+</parameter>
+<parameter name="status" type="int">
+</parameter>
+</method>
+</interface>
<class name="ThumbnailUtils"
extends="java.lang.Object"
abstract="false"
@@ -150338,9 +150409,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"
@@ -150370,7 +150441,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>
@@ -201436,6 +201507,19 @@
native="false"
synchronized="false"
static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="setColorFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
final="false"
deprecated="not deprecated"
visibility="public"
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index 39e14e4..6a79c6d 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -268,7 +268,10 @@
char anr_traces_path[PATH_MAX];
strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path));
strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path));
- rename(traces_path, anr_traces_path);
+ if (rename(traces_path, anr_traces_path) && errno != ENOENT) {
+ fprintf(stderr, "rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
+ return NULL; // Can't rename old traces.txt -- no permission? -- leave it alone instead
+ }
/* create a new, empty traces.txt file to receive stack dumps */
int fd = open(traces_path, O_CREAT | O_WRONLY | O_TRUNC, 0666); /* -rw-rw-rw- */
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index f7cb227..942a303 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -157,13 +157,18 @@
long numIterationsLeft = gNumRepetitions;
MediaSource::ReadOptions options;
+ int64_t sumDecodeUs = 0;
+
while (numIterationsLeft-- > 0) {
long numFrames = 0;
MediaBuffer *buffer;
for (;;) {
+ int64_t startDecodeUs = getNowUs();
status_t err = rawSource->read(&buffer, &options);
+ int64_t delayDecodeUs = getNowUs() - startDecodeUs;
+
options.clearSeekTo();
if (err != OK) {
@@ -182,6 +187,8 @@
fflush(stdout);
}
+ sumDecodeUs += delayDecodeUs;
+
buffer->release();
buffer = NULL;
@@ -210,6 +217,8 @@
int64_t delay = getNowUs() - startTime;
printf("avg. %.2f fps\n", n * 1E6 / delay);
+ printf("avg. time to decode one buffer %.2f usecs\n",
+ (double)sumDecodeUs / n);
printf("decoded a total of %d frame(s).\n", n);
}
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/app/Dialog.java b/core/java/android/app/Dialog.java
index ed38240..4598bb5 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -822,11 +822,6 @@
final SearchManager searchManager = (SearchManager) mContext
.getSystemService(Context.SEARCH_SERVICE);
- // can't start search without an associated activity (e.g a system dialog)
- if (!searchManager.hasIdent()) {
- return false;
- }
-
// associate search with owner activity if possible (otherwise it will default to
// global search).
final ComponentName appName = getAssociatedActivity();
diff --git a/core/java/android/app/FullBackupAgent.java b/core/java/android/app/FullBackupAgent.java
index d89db96..db198ad 100644
--- a/core/java/android/app/FullBackupAgent.java
+++ b/core/java/android/app/FullBackupAgent.java
@@ -48,7 +48,8 @@
}
// That's the file set; now back it all up
- FileBackupHelper helper = new FileBackupHelper(this, (String[])allFiles.toArray());
+ FileBackupHelper helper = new FileBackupHelper(this,
+ allFiles.toArray(new String[allFiles.size()]));
helper.performBackup(oldState, data, newState);
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index e4c1ba6..581b436 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -16,6 +16,9 @@
package android.app;
+import com.android.common.Patterns;
+import com.android.common.speech.Recognition;
+
import static android.app.SuggestionsAdapter.getColumnString;
import android.content.ActivityNotFoundException;
@@ -67,9 +70,6 @@
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
-import com.android.common.Patterns;
-import com.android.common.speech.Recognition;
-
import java.util.ArrayList;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicLong;
@@ -89,10 +89,7 @@
private static final String INSTANCE_KEY_COMPONENT = "comp";
private static final String INSTANCE_KEY_APPDATA = "data";
- private static final String INSTANCE_KEY_GLOBALSEARCH = "glob";
- private static final String INSTANCE_KEY_STORED_COMPONENT = "sComp";
private static final String INSTANCE_KEY_STORED_APPDATA = "sData";
- private static final String INSTANCE_KEY_PREVIOUS_COMPONENTS = "sPrev";
private static final String INSTANCE_KEY_USER_QUERY = "uQry";
// The string used for privateImeOptions to identify to the IME that it should not show
@@ -115,19 +112,8 @@
private SearchableInfo mSearchable;
private ComponentName mLaunchComponent;
private Bundle mAppSearchData;
- private boolean mGlobalSearchMode;
private Context mActivityContext;
private SearchManager mSearchManager;
-
- // Values we store to allow user to toggle between in-app search and global search.
- private ComponentName mStoredComponentName;
- private Bundle mStoredAppSearchData;
-
- // stack of previous searchables, to support the BACK key after
- // SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE.
- // The top of the stack (= previous searchable) is the last element of the list,
- // since adding and removing is efficient at the end of an ArrayList.
- private ArrayList<ComponentName> mPreviousComponents;
// For voice searching
private final Intent mVoiceWebSearchIntent;
@@ -158,7 +144,7 @@
* @param context Application Context we can use for system acess
*/
public SearchDialog(Context context, SearchManager searchManager) {
- super(context, com.android.internal.R.style.Theme_GlobalSearchBar);
+ super(context, com.android.internal.R.style.Theme_SearchBar);
// Save voice intent for later queries/launching
mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
@@ -241,14 +227,8 @@
* @return true if search dialog launched, false if not
*/
public boolean show(String initialQuery, boolean selectInitialQuery,
- ComponentName componentName, Bundle appSearchData, boolean globalSearch) {
-
- // Reset any stored values from last time dialog was shown.
- mStoredComponentName = null;
- mStoredAppSearchData = null;
-
- boolean success = doShow(initialQuery, selectInitialQuery, componentName, appSearchData,
- globalSearch);
+ ComponentName componentName, Bundle appSearchData) {
+ boolean success = doShow(initialQuery, selectInitialQuery, componentName, appSearchData);
if (success) {
// Display the drop down as soon as possible instead of waiting for the rest of the
// pending UI stuff to get done, so that things appear faster to the user.
@@ -257,67 +237,16 @@
return success;
}
- private boolean isInRealAppSearch() {
- return !mGlobalSearchMode
- && (mPreviousComponents == null || mPreviousComponents.isEmpty());
- }
-
/**
- * Called in response to a press of the hard search button in
- * {@link #onKeyDown(int, KeyEvent)}, this method toggles between in-app
- * search and global search when relevant.
- *
- * If pressed within an in-app search context, this switches the search dialog out to
- * global search. If pressed within a global search context that was originally an in-app
- * search context, this switches back to the in-app search context. If pressed within a
- * global search context that has no original in-app search context (e.g., global search
- * from Home), this does nothing.
- *
- * @return false if we wanted to toggle context but could not do so successfully, true
- * in all other cases
- */
- private boolean toggleGlobalSearch() {
- String currentSearchText = mSearchAutoComplete.getText().toString();
- if (!mGlobalSearchMode) {
- mStoredComponentName = mLaunchComponent;
- mStoredAppSearchData = mAppSearchData;
-
- // If this is the browser, we have a special case to not show the icon to the left
- // of the text field, for extra space for url entry (this should be reconciled in
- // Eclair). So special case a second tap of the search button to remove any
- // already-entered text so that we can be sure to show the "Quick Search Box" hint
- // text to still make it clear to the user that we've jumped out to global search.
- //
- // TODO: When the browser icon issue is reconciled in Eclair, remove this special case.
- if (isBrowserSearch()) currentSearchText = "";
-
- cancel();
- mSearchManager.startGlobalSearch(currentSearchText, false, mStoredAppSearchData);
- return true;
- } else {
- if (mStoredComponentName != null) {
- // This means we should toggle *back* to an in-app search context from
- // global search.
- return doShow(currentSearchText, false, mStoredComponentName,
- mStoredAppSearchData, false);
- } else {
- return true;
- }
- }
- }
-
- /**
- * Does the rest of the work required to show the search dialog. Called by both
- * {@link #show(String, boolean, ComponentName, Bundle, boolean)} and
- * {@link #toggleGlobalSearch()}.
- *
+ * Does the rest of the work required to show the search dialog. Called by
+ * {@link #show(String, boolean, ComponentName, Bundle)} and
+ *
* @return true if search dialog showed, false if not
*/
private boolean doShow(String initialQuery, boolean selectInitialQuery,
- ComponentName componentName, Bundle appSearchData,
- boolean globalSearch) {
+ ComponentName componentName, Bundle appSearchData) {
// set up the searchable and show the dialog
- if (!show(componentName, appSearchData, globalSearch)) {
+ if (!show(componentName, appSearchData)) {
return false;
}
@@ -335,38 +264,24 @@
*
* @return <code>true</code> if search dialog launched
*/
- private boolean show(ComponentName componentName, Bundle appSearchData,
- boolean globalSearch) {
+ private boolean show(ComponentName componentName, Bundle appSearchData) {
if (DBG) {
Log.d(LOG_TAG, "show(" + componentName + ", "
- + appSearchData + ", " + globalSearch + ")");
+ + appSearchData + ")");
}
SearchManager searchManager = (SearchManager)
mContext.getSystemService(Context.SEARCH_SERVICE);
- // Try to get the searchable info for the provided component (or for global search,
- // if globalSearch == true).
- mSearchable = searchManager.getSearchableInfo(componentName, globalSearch);
-
- // If we got back nothing, and it wasn't a request for global search, then try again
- // for global search, as we'll try to launch that in lieu of any component-specific search.
- if (!globalSearch && mSearchable == null) {
- globalSearch = true;
- mSearchable = searchManager.getSearchableInfo(componentName, globalSearch);
- }
+ // Try to get the searchable info for the provided component.
+ mSearchable = searchManager.getSearchableInfo(componentName, false);
- // If there's not even a searchable info available for global search, then really give up.
if (mSearchable == null) {
- Log.w(LOG_TAG, "No global search provider.");
return false;
}
mLaunchComponent = componentName;
mAppSearchData = appSearchData;
- // Using globalSearch here is just an optimization, just calling
- // isDefaultSearchable() should always give the same result.
- mGlobalSearchMode = globalSearch || searchManager.isDefaultSearchable(mSearchable);
mActivityContext = mSearchable.getActivityContext(getContext());
// show the dialog. this will call onStart().
@@ -375,20 +290,6 @@
// of any bad state in the AutoCompleteTextView etc
createContentView();
- // The Dialog uses a ContextThemeWrapper for the context; use this to change the
- // theme out from underneath us, between the global search theme and the in-app
- // search theme. They are identical except that the global search theme does not
- // dim the background of the window (because global search is full screen so it's
- // not needed and this should save a little bit of time on global search invocation).
- Object context = getContext();
- if (context instanceof ContextThemeWrapper) {
- ContextThemeWrapper wrapper = (ContextThemeWrapper) context;
- if (globalSearch) {
- wrapper.setTheme(com.android.internal.R.style.Theme_GlobalSearchBar);
- } else {
- wrapper.setTheme(com.android.internal.R.style.Theme_SearchBar);
- }
- }
show();
}
updateUI();
@@ -414,7 +315,6 @@
mSearchable = null;
mActivityContext = null;
mUserQuery = null;
- mPreviousComponents = null;
}
/**
@@ -428,7 +328,7 @@
mWorkingSpinner.setVisible(working, false);
mWorkingSpinner.invalidateSelf();
}
-
+
/**
* Closes and gets rid of the suggestions adapter.
*/
@@ -442,7 +342,7 @@
}
mSuggestionsAdapter = null;
}
-
+
/**
* Save the minimal set of data necessary to recreate the search
*
@@ -458,10 +358,6 @@
// setup info so I can recreate this particular search
bundle.putParcelable(INSTANCE_KEY_COMPONENT, mLaunchComponent);
bundle.putBundle(INSTANCE_KEY_APPDATA, mAppSearchData);
- bundle.putBoolean(INSTANCE_KEY_GLOBALSEARCH, mGlobalSearchMode);
- bundle.putParcelable(INSTANCE_KEY_STORED_COMPONENT, mStoredComponentName);
- bundle.putBundle(INSTANCE_KEY_STORED_APPDATA, mStoredAppSearchData);
- bundle.putParcelableArrayList(INSTANCE_KEY_PREVIOUS_COMPONENTS, mPreviousComponents);
bundle.putString(INSTANCE_KEY_USER_QUERY, mUserQuery);
return bundle;
@@ -481,22 +377,10 @@
ComponentName launchComponent = savedInstanceState.getParcelable(INSTANCE_KEY_COMPONENT);
Bundle appSearchData = savedInstanceState.getBundle(INSTANCE_KEY_APPDATA);
- boolean globalSearch = savedInstanceState.getBoolean(INSTANCE_KEY_GLOBALSEARCH);
- ComponentName storedComponentName =
- savedInstanceState.getParcelable(INSTANCE_KEY_STORED_COMPONENT);
- Bundle storedAppSearchData =
- savedInstanceState.getBundle(INSTANCE_KEY_STORED_APPDATA);
- ArrayList<ComponentName> previousComponents =
- savedInstanceState.getParcelableArrayList(INSTANCE_KEY_PREVIOUS_COMPONENTS);
String userQuery = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY);
- // Set stored state
- mStoredComponentName = storedComponentName;
- mStoredAppSearchData = storedAppSearchData;
- mPreviousComponents = previousComponents;
-
// show the dialog.
- if (!doShow(userQuery, false, launchComponent, appSearchData, globalSearch)) {
+ if (!doShow(userQuery, false, launchComponent, appSearchData)) {
// for some reason, we couldn't re-instantiate
return;
}
@@ -506,7 +390,7 @@
* Called after resources have changed, e.g. after screen rotation or locale change.
*/
public void onConfigurationChanged() {
- if (isShowing()) {
+ if (mSearchable != null && isShowing()) {
// Redraw (resources may have changed)
updateSearchButton();
updateSearchAppIcon();
@@ -571,19 +455,13 @@
// we dismiss the entire dialog instead
mSearchAutoComplete.setDropDownDismissedOnCompletion(false);
- if (!isInRealAppSearch()) {
- mSearchAutoComplete.setDropDownAlwaysVisible(true); // fill space until results come in
- } else {
- mSearchAutoComplete.setDropDownAlwaysVisible(false);
- }
-
mSearchAutoComplete.setForceIgnoreOutsideTouch(true);
// attach the suggestions adapter, if suggestions are available
// The existence of a suggestions authority is the proxy for "suggestions available here"
if (mSearchable.getSuggestAuthority() != null) {
mSuggestionsAdapter = new SuggestionsAdapter(getContext(), this, mSearchable,
- mOutsideDrawablesCache, mGlobalSearchMode);
+ mOutsideDrawablesCache);
mSearchAutoComplete.setAdapter(mSuggestionsAdapter);
}
}
@@ -611,7 +489,7 @@
// global search, for extra space for url entry.
//
// TODO: Remove this special case once the issue has been reconciled in Eclair.
- if (mGlobalSearchMode || isBrowserSearch()) {
+ if (isBrowserSearch()) {
mAppIcon.setImageResource(0);
mAppIcon.setVisibility(View.GONE);
mSearchPlate.setPadding(SEARCH_PLATE_LEFT_PADDING_GLOBAL,
@@ -705,15 +583,13 @@
/**
* Hack to determine whether this is the browser, so we can remove the browser icon
- * to the left of the search field, as a special requirement for Donut.
- *
- * TODO: For Eclair, reconcile this with the rest of the global search UI.
+ * to the left of the search field.
*/
private boolean isBrowserSearch() {
return mLaunchComponent.flattenToShortString().startsWith("com.android.browser/");
}
- /**
+ /*
* Listeners of various types
*/
@@ -769,7 +645,7 @@
return super.onKeyDown(keyCode, event);
}
-
+
/**
* Callback to watch the textedit field for empty/non-empty
*/
@@ -799,12 +675,8 @@
if (mSearchable.autoUrlDetect() && !mSearchAutoComplete.isPerformingCompletion()) {
// The user changed the query, check if it is a URL and if so change the search
// button in the soft keyboard to the 'Go' button.
- int options = (mSearchAutoComplete.getImeOptions() & (~EditorInfo.IME_MASK_ACTION));
- if (Patterns.WEB_URL.matcher(mUserQuery).matches()) {
- options = options | EditorInfo.IME_ACTION_GO;
- } else {
- options = options | EditorInfo.IME_ACTION_SEARCH;
- }
+ int options = (mSearchAutoComplete.getImeOptions() & (~EditorInfo.IME_MASK_ACTION))
+ | EditorInfo.IME_ACTION_GO;
if (options != mSearchAutoCompleteImeOptions) {
mSearchAutoCompleteImeOptions = options;
mSearchAutoComplete.setImeOptions(options);
@@ -881,7 +753,8 @@
if (searchable.getVoiceSearchLaunchWebSearch()) {
getContext().startActivity(mVoiceWebSearchIntent);
} else if (searchable.getVoiceSearchLaunchRecognizer()) {
- Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent);
+ Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent,
+ searchable);
getContext().startActivity(appSearchIntent);
}
} catch (ActivityNotFoundException e) {
@@ -899,8 +772,8 @@
* @param baseIntent The voice app search intent to start from
* @return A completely-configured intent ready to send to the voice search activity
*/
- private Intent createVoiceAppSearchIntent(Intent baseIntent) {
- ComponentName searchActivity = mSearchable.getSearchActivity();
+ private Intent createVoiceAppSearchIntent(Intent baseIntent, SearchableInfo searchable) {
+ ComponentName searchActivity = searchable.getSearchActivity();
// create the necessary intent to set up a search-and-forward operation
// in the voice search system. We have to keep the bundle separate,
@@ -930,17 +803,17 @@
String language = null;
int maxResults = 1;
Resources resources = mActivityContext.getResources();
- if (mSearchable.getVoiceLanguageModeId() != 0) {
- languageModel = resources.getString(mSearchable.getVoiceLanguageModeId());
+ if (searchable.getVoiceLanguageModeId() != 0) {
+ languageModel = resources.getString(searchable.getVoiceLanguageModeId());
}
- if (mSearchable.getVoicePromptTextId() != 0) {
- prompt = resources.getString(mSearchable.getVoicePromptTextId());
+ if (searchable.getVoicePromptTextId() != 0) {
+ prompt = resources.getString(searchable.getVoicePromptTextId());
}
- if (mSearchable.getVoiceLanguageId() != 0) {
- language = resources.getString(mSearchable.getVoiceLanguageId());
+ if (searchable.getVoiceLanguageId() != 0) {
+ language = resources.getString(searchable.getVoiceLanguageId());
}
- if (mSearchable.getVoiceMaxResults() != 0) {
- maxResults = mSearchable.getVoiceMaxResults();
+ if (searchable.getVoiceMaxResults() != 0) {
+ maxResults = searchable.getVoiceMaxResults();
}
voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel);
voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt);
@@ -1140,14 +1013,9 @@
*/
protected void launchQuerySearch(int actionKey, String actionMsg) {
String query = mSearchAutoComplete.getText().toString();
- String action = mGlobalSearchMode ? Intent.ACTION_WEB_SEARCH : Intent.ACTION_SEARCH;
+ String action = Intent.ACTION_SEARCH;
Intent intent = createIntent(action, null, null, query, null,
- actionKey, actionMsg, null);
- // Allow GlobalSearch to log and create shortcut for searches launched by
- // the search button, enter key or an action key.
- if (mGlobalSearchMode) {
- mSuggestionsAdapter.reportSearch(query);
- }
+ actionKey, actionMsg);
launchIntent(intent);
}
@@ -1160,7 +1028,7 @@
protected boolean launchSuggestion(int position) {
return launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null);
}
-
+
/**
* Launches an intent based on a suggestion.
*
@@ -1177,20 +1045,7 @@
Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg);
- // report back about the click
- if (mGlobalSearchMode) {
- // in global search mode, do it via cursor
- mSuggestionsAdapter.callCursorOnClick(c, position, actionKey, actionMsg);
- } else if (intent != null
- && mPreviousComponents != null
- && !mPreviousComponents.isEmpty()) {
- // in-app search (and we have pivoted in as told by mPreviousComponents,
- // which is used for keeping track of what we pop back to when we are pivoting into
- // in app search.)
- reportInAppClickToGlobalSearch(c, intent);
- }
-
- // launch the intent
+ // launch the intent
launchIntent(intent);
return true;
@@ -1199,163 +1054,28 @@
}
/**
- * Report a click from an in app search result back to global search for shortcutting porpoises.
- *
- * @param c The cursor that is pointing to the clicked position.
- * @param intent The intent that will be launched for the click.
- */
- private void reportInAppClickToGlobalSearch(Cursor c, Intent intent) {
- // for in app search, still tell global search via content provider
- Uri uri = getClickReportingUri();
- final ContentValues cv = new ContentValues();
- cv.put(SearchManager.SEARCH_CLICK_REPORT_COLUMN_QUERY, mUserQuery);
- final ComponentName source = mSearchable.getSearchActivity();
- cv.put(SearchManager.SEARCH_CLICK_REPORT_COLUMN_COMPONENT, source.flattenToShortString());
-
- // grab the intent columns from the intent we created since it has additional
- // logic for falling back on the searchable default
- cv.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION, intent.getAction());
- cv.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, intent.getDataString());
- cv.put(SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME,
- intent.getComponent().flattenToShortString());
-
- // ensure the icons will work for global search
- cv.put(SearchManager.SUGGEST_COLUMN_ICON_1,
- wrapIconForPackage(
- mSearchable.getSuggestPackage(),
- getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_1)));
- cv.put(SearchManager.SUGGEST_COLUMN_ICON_2,
- wrapIconForPackage(
- mSearchable.getSuggestPackage(),
- getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_2)));
-
- // the rest can be passed through directly
- cv.put(SearchManager.SUGGEST_COLUMN_FORMAT,
- getColumnString(c, SearchManager.SUGGEST_COLUMN_FORMAT));
- cv.put(SearchManager.SUGGEST_COLUMN_TEXT_1,
- getColumnString(c, SearchManager.SUGGEST_COLUMN_TEXT_1));
- cv.put(SearchManager.SUGGEST_COLUMN_TEXT_2,
- getColumnString(c, SearchManager.SUGGEST_COLUMN_TEXT_2));
- cv.put(SearchManager.SUGGEST_COLUMN_QUERY,
- getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY));
- cv.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
- getColumnString(c, SearchManager.SUGGEST_COLUMN_SHORTCUT_ID));
- // note: deliberately omitting background color since it is only for global search
- // "more results" entries
- mContext.getContentResolver().insert(uri, cv);
- }
-
- /**
- * @return A URI appropriate for reporting a click.
- */
- private Uri getClickReportingUri() {
- Uri.Builder uriBuilder = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SearchManager.SEARCH_CLICK_REPORT_AUTHORITY);
-
- uriBuilder.appendPath(SearchManager.SEARCH_CLICK_REPORT_URI_PATH);
-
- return uriBuilder
- .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel()
- .fragment("") // TODO: Remove, workaround for a bug in Uri.writeToParcel()
- .build();
- }
-
- /**
- * Wraps an icon for a particular package. If the icon is a resource id, it is converted into
- * an android.resource:// URI.
- *
- * @param packageName The source of the icon
- * @param icon The icon retrieved from a suggestion column
- * @return An icon string appropriate for the package.
- */
- private String wrapIconForPackage(String packageName, String icon) {
- if (icon == null || icon.length() == 0 || "0".equals(icon)) {
- // SearchManager specifies that null or zero can be returned to indicate
- // no icon. We also allow empty string.
- return null;
- } else if (!Character.isDigit(icon.charAt(0))){
- return icon;
- } else {
- return new Uri.Builder()
- .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
- .authority(packageName)
- .encodedPath(icon)
- .toString();
- }
- }
-
- /**
* Launches an intent, including any special intent handling.
*/
private void launchIntent(Intent intent) {
if (intent == null) {
return;
}
- if (handleSpecialIntent(intent)){
- return;
- }
Log.d(LOG_TAG, "launching " + intent);
try {
- // in global search mode, we send the activity straight to the original suggestion
- // source. this is because GlobalSearch may not have permission to launch the
- // intent, and to avoid the extra step of going through GlobalSearch.
- if (mGlobalSearchMode) {
- launchGlobalSearchIntent(intent);
- if (mStoredComponentName != null) {
- // If we're embedded in an application, dismiss the dialog.
- // This ensures that if the intent is handled by the current
- // activity, it's not obscured by the dialog.
- dismiss();
- }
- } else {
- // If the intent was created from a suggestion, it will always have an explicit
- // component here.
- Log.i(LOG_TAG, "Starting (as ourselves) " + intent.toURI());
- getContext().startActivity(intent);
- // If the search switches to a different activity,
- // SearchDialogWrapper#performActivityResuming
- // will handle hiding the dialog when the next activity starts, but for
- // real in-app search, we still need to dismiss the dialog.
- if (isInRealAppSearch()) {
- dismiss();
- }
- }
+ // If the intent was created from a suggestion, it will always have an explicit
+ // component here.
+ Log.i(LOG_TAG, "Starting (as ourselves) " + intent.toURI());
+ getContext().startActivity(intent);
+ // If the search switches to a different activity,
+ // SearchDialogWrapper#performActivityResuming
+ // will handle hiding the dialog when the next activity starts, but for
+ // real in-app search, we still need to dismiss the dialog.
+ dismiss();
} catch (RuntimeException ex) {
Log.e(LOG_TAG, "Failed launch activity: " + intent, ex);
}
}
- private void launchGlobalSearchIntent(Intent intent) {
- final String packageName;
- // GlobalSearch puts the original source of the suggestion in the
- // 'component name' column. If set, we send the intent to that activity.
- // We trust GlobalSearch to always set this to the suggestion source.
- String intentComponent = intent.getStringExtra(SearchManager.COMPONENT_NAME_KEY);
- if (intentComponent != null) {
- ComponentName componentName = ComponentName.unflattenFromString(intentComponent);
- intent.setComponent(componentName);
- intent.removeExtra(SearchManager.COMPONENT_NAME_KEY);
- // Launch the intent as the suggestion source.
- // This prevents sources from using the search dialog to launch
- // intents that they don't have permission for themselves.
- packageName = componentName.getPackageName();
- } else {
- // If there is no component in the suggestion, it must be a built-in suggestion
- // from GlobalSearch (e.g. "Search the web for") or the intent
- // launched when pressing the search/go button in the search dialog.
- // Launch the intent with the permissions of GlobalSearch.
- packageName = mSearchable.getSearchActivity().getPackageName();
- }
-
- // Launch all global search suggestions as new tasks, since they don't relate
- // to the current task.
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- setBrowserApplicationId(intent);
-
- startActivityInPackage(intent, packageName);
- }
-
/**
* If the intent is to open an HTTP or HTTPS URL, we set
* {@link Browser#EXTRA_APPLICATION_ID} so that any existing browser window that
@@ -1372,106 +1092,6 @@
}
/**
- * Starts an activity as if it had been started by the given package.
- *
- * @param intent The description of the activity to start.
- * @param packageName
- * @throws ActivityNotFoundException If the intent could not be resolved to
- * and existing activity.
- * @throws SecurityException If the package does not have permission to start
- * start the activity.
- * @throws AndroidRuntimeException If some other error occurs.
- */
- private void startActivityInPackage(Intent intent, String packageName) {
- try {
- int uid = ActivityThread.getPackageManager().getPackageUid(packageName);
- if (uid < 0) {
- throw new AndroidRuntimeException("Package UID not found " + packageName);
- }
- String resolvedType = intent.resolveTypeIfNeeded(getContext().getContentResolver());
- IBinder resultTo = null;
- String resultWho = null;
- int requestCode = -1;
- boolean onlyIfNeeded = false;
- Log.i(LOG_TAG, "Starting (uid " + uid + ", " + packageName + ") " + intent.toURI());
- int result = ActivityManagerNative.getDefault().startActivityInPackage(
- uid, intent, resolvedType, resultTo, resultWho, requestCode, onlyIfNeeded);
- checkStartActivityResult(result, intent);
- } catch (RemoteException ex) {
- throw new AndroidRuntimeException(ex);
- }
- }
-
- // Stolen from Instrumentation.checkStartActivityResult()
- private static void checkStartActivityResult(int res, Intent intent) {
- if (res >= IActivityManager.START_SUCCESS) {
- return;
- }
- switch (res) {
- case IActivityManager.START_INTENT_NOT_RESOLVED:
- case IActivityManager.START_CLASS_NOT_FOUND:
- if (intent.getComponent() != null)
- throw new ActivityNotFoundException(
- "Unable to find explicit activity class "
- + intent.getComponent().toShortString()
- + "; have you declared this activity in your AndroidManifest.xml?");
- throw new ActivityNotFoundException(
- "No Activity found to handle " + intent);
- case IActivityManager.START_PERMISSION_DENIED:
- throw new SecurityException("Not allowed to start activity "
- + intent);
- case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
- throw new AndroidRuntimeException(
- "FORWARD_RESULT_FLAG used while also requesting a result");
- default:
- throw new AndroidRuntimeException("Unknown error code "
- + res + " when starting " + intent);
- }
- }
-
- /**
- * Handles the special intent actions declared in {@link SearchManager}.
- *
- * @return <code>true</code> if the intent was handled.
- */
- private boolean handleSpecialIntent(Intent intent) {
- String action = intent.getAction();
- if (SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE.equals(action)) {
- handleChangeSourceIntent(intent);
- return true;
- }
- return false;
- }
-
- /**
- * Handles {@link SearchManager#INTENT_ACTION_CHANGE_SEARCH_SOURCE}.
- */
- private void handleChangeSourceIntent(Intent intent) {
- Uri dataUri = intent.getData();
- if (dataUri == null) {
- Log.w(LOG_TAG, "SearchManager.INTENT_ACTION_CHANGE_SOURCE without intent data.");
- return;
- }
- ComponentName componentName = ComponentName.unflattenFromString(dataUri.toString());
- if (componentName == null) {
- Log.w(LOG_TAG, "Invalid ComponentName: " + dataUri);
- return;
- }
- if (DBG) Log.d(LOG_TAG, "Switching to " + componentName);
-
- pushPreviousComponent(mLaunchComponent);
- if (!show(componentName, mAppSearchData, false)) {
- Log.w(LOG_TAG, "Failed to switch to source " + componentName);
- popPreviousComponent();
- return;
- }
-
- String query = intent.getStringExtra(SearchManager.QUERY);
- setUserQuery(query);
- mSearchAutoComplete.showDropDown();
- }
-
- /**
* Sets the list item selection in the AutoCompleteTextView's ListView.
*/
public void setListSelection(int index) {
@@ -1479,61 +1099,6 @@
}
/**
- * Checks if there are any previous searchable components in the history stack.
- */
- private boolean hasPreviousComponent() {
- return mPreviousComponents != null && !mPreviousComponents.isEmpty();
- }
-
- /**
- * Saves the previous component that was searched, so that we can go
- * back to it.
- */
- private void pushPreviousComponent(ComponentName componentName) {
- if (mPreviousComponents == null) {
- mPreviousComponents = new ArrayList<ComponentName>();
- }
- mPreviousComponents.add(componentName);
- }
-
- /**
- * Pops the previous component off the stack and returns it.
- *
- * @return The component name, or <code>null</code> if there was
- * no previous component.
- */
- private ComponentName popPreviousComponent() {
- if (!hasPreviousComponent()) {
- return null;
- }
- return mPreviousComponents.remove(mPreviousComponents.size() - 1);
- }
-
- /**
- * Goes back to the previous component that was searched, if any.
- *
- * @return <code>true</code> if there was a previous component that we could go back to.
- */
- private boolean backToPreviousComponent() {
- ComponentName previous = popPreviousComponent();
- if (previous == null) {
- return false;
- }
-
- if (!show(previous, mAppSearchData, false)) {
- Log.w(LOG_TAG, "Failed to switch to source " + previous);
- return false;
- }
-
- // must touch text to trigger suggestions
- // TODO: should this be the text as it was when the user left
- // the source that we are now going back to?
- String query = mSearchAutoComplete.getText().toString();
- setUserQuery(query);
- return true;
- }
-
- /**
* When a particular suggestion has been selected, perform the various lookups required
* to use the suggestion. This includes checking the cursor for suggestion-specific data,
* and/or falling back to the XML for defaults; It also creates REST style Uri data when
@@ -1582,10 +1147,9 @@
String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY);
String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
- String mode = mGlobalSearchMode ? SearchManager.MODE_GLOBAL_SEARCH_SUGGESTION : null;
return createIntent(action, dataUri, extraData, query, componentName, actionKey,
- actionMsg, mode);
+ actionMsg);
} catch (RuntimeException e ) {
int rowNum;
try { // be really paranoid now
@@ -1616,16 +1180,13 @@
* @return The intent.
*/
private Intent createIntent(String action, Uri data, String extraData, String query,
- String componentName, int actionKey, String actionMsg, String mode) {
+ String componentName, int actionKey, String actionMsg) {
// Now build the Intent
Intent intent = new Intent(action);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// We need CLEAR_TOP to avoid reusing an old task that has other activities
// on top of the one we want. We don't want to do this in in-app search though,
// as it can be destructive to the activity stack.
- if (mGlobalSearchMode) {
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- }
if (data != null) {
intent.setData(data);
}
@@ -1636,9 +1197,6 @@
if (extraData != null) {
intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
}
- if (componentName != null) {
- intent.putExtra(SearchManager.COMPONENT_NAME_KEY, componentName);
- }
if (mAppSearchData != null) {
intent.putExtra(SearchManager.APP_DATA, mAppSearchData);
}
@@ -1646,16 +1204,10 @@
intent.putExtra(SearchManager.ACTION_KEY, actionKey);
intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
}
- if (mode != null) {
- intent.putExtra(SearchManager.SEARCH_MODE, mode);
- }
- // Only allow 3rd-party intents from GlobalSearch
- if (!mGlobalSearchMode) {
- intent.setComponent(mSearchable.getSearchActivity());
- }
+ intent.setComponent(mSearchable.getSearchActivity());
return intent;
}
-
+
/**
* For a given suggestion and a given cursor row, get the action message. If not provided
* by the specific row/column, also check for a single definition (for the action key).
@@ -1812,12 +1364,8 @@
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0)) {
return;
}
- // Otherwise, go back to any previous source (e.g. back to QSB when
- // pivoted into a source.
- if (!backToPreviousComponent()) {
- // If no previous source, close search dialog
- cancel();
- }
+ // Close search dialog
+ cancel();
}
/**
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 5a9a675..52cdc74 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -350,7 +350,7 @@
* <p><b>Configuring your Content Provider to Receive Suggestion Queries.</b> The basic job of
* a search suggestions {@link android.content.ContentProvider Content Provider} is to provide
* "live" (while-you-type) conversion of the user's query text into a set of zero or more
- * suggestions. Each application is free to define the conversion, and as described above there are
+ * suggestions. Each application is free to define the conversion, and as described above there are
* many possible solutions. This section simply defines how to communicate with the suggestion
* provider.
*
@@ -360,7 +360,8 @@
*
* <p>Every query includes a Uri, and the Search Manager will format the Uri as shown:
* <p><pre class="prettyprint">
- * content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY</pre>
+ * content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY
+ * </pre>
*
* <p>Your Content Provider can receive the query text in one of two ways.
* <ul>
@@ -379,7 +380,7 @@
* <p><b>Providing access to Content Providers that require permissions.</b> If your content
* provider declares an android:readPermission in your application's manifest, you must provide
* access to the search infrastructure to the search suggestion path by including a path-permission
- * that grants android:readPermission access to "android.permission.GLOBAL_SEARCH". Granting access
+ * that grants android:readPermission access to "android.permission.GLOBAL_SEARCH". Granting access
* explicitly to the search infrastructure ensures it will be able to access the search suggestions
* without needing to know ahead of time any other details of the permissions protecting your
* provider. Content providers that require no permissions are already available to the search
@@ -546,7 +547,8 @@
* taken directly to a specific result.
* <ul>
* <li><b>Action:</b> {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}</li>
- * <li><b>Data:</b> a complete Uri, supplied by the cursor, that identifies the desired data.</li>
+ * <li><b>Data:</b> a complete Uri, supplied by the cursor, that identifies the desired data.
+ * </li>
* <li><b>Query:</b> query text supplied with the suggestion (probably ignored)</li>
* </ul>
* </li>
@@ -570,7 +572,7 @@
*
* <p><b>Suggestion Rewriting.</b> If the user navigates through the suggestions list, the UI
* may temporarily rewrite the user's query with a query that matches the currently selected
- * suggestion. This enables the user to see what query is being suggested, and also allows the user
+ * suggestion. This enables the user to see what query is being suggested, and also allows the user
* to click or touch in the entry EditText element and make further edits to the query before
* dispatching it. In order to perform this correctly, the Search UI needs to know exactly what
* text to rewrite the query with.
@@ -1289,15 +1291,6 @@
public final static String SEARCH_MODE = "search_mode";
/**
- * Value for the {@link #SEARCH_MODE} key.
- * This is used if the intent was launched by clicking a suggestion in global search
- * mode (Quick Search Box).
- *
- * @hide
- */
- public static final String MODE_GLOBAL_SEARCH_SUGGESTION = "global_search_suggestion";
-
- /**
* Intent extra data key: Use this key with Intent.ACTION_SEARCH and
* {@link android.content.Intent#getIntExtra content.Intent.getIntExtra()}
* to obtain the keycode that the user used to trigger this query. It will be zero if the
@@ -1308,14 +1301,6 @@
public final static String ACTION_KEY = "action_key";
/**
- * Intent component name key: This key will be used for the extra populated by the
- * {@link #SUGGEST_COLUMN_INTENT_COMPONENT_NAME} column.
- *
- * {@hide}
- */
- public final static String COMPONENT_NAME_KEY = "intent_component_name_key";
-
- /**
* Intent extra data key: This key will be used for the extra populated by the
* {@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA} column.
*/
@@ -1329,58 +1314,6 @@
public final static String EXTRA_SELECT_QUERY = "select_query";
/**
- * Defines the constants used in the communication between {@link android.app.SearchDialog} and
- * the global search provider via {@link Cursor#respond(android.os.Bundle)}.
- *
- * @hide
- */
- public static class DialogCursorProtocol {
-
- /**
- * The sent bundle will contain this integer key, with a value set to one of the events
- * below.
- */
- public final static String METHOD = "DialogCursorProtocol.method";
-
- /**
- * After data has been refreshed.
- */
- public final static int POST_REFRESH = 0;
- public final static String POST_REFRESH_RECEIVE_ISPENDING
- = "DialogCursorProtocol.POST_REFRESH.isPending";
- public final static String POST_REFRESH_RECEIVE_DISPLAY_NOTIFY
- = "DialogCursorProtocol.POST_REFRESH.displayNotify";
-
- /**
- * When a position has been clicked.
- */
- public final static int CLICK = 2;
- public final static String CLICK_SEND_POSITION
- = "DialogCursorProtocol.CLICK.sendPosition";
- public final static String CLICK_SEND_MAX_DISPLAY_POS
- = "DialogCursorProtocol.CLICK.sendDisplayPosition";
- public final static String CLICK_SEND_ACTION_KEY
- = "DialogCursorProtocol.CLICK.sendActionKey";
- public final static String CLICK_SEND_ACTION_MSG
- = "DialogCursorProtocol.CLICK.sendActionMsg";
- public final static String CLICK_RECEIVE_SELECTED_POS
- = "DialogCursorProtocol.CLICK.receiveSelectedPosition";
-
- /**
- * When the threshold received in {@link #POST_REFRESH_RECEIVE_DISPLAY_NOTIFY} is displayed.
- */
- public final static int THRESH_HIT = 3;
-
- /**
- * When a search is started without using a suggestion.
- */
- public final static int SEARCH = 4;
- public final static String SEARCH_SEND_MAX_DISPLAY_POS
- = "DialogCursorProtocol.SEARCH.sendDisplayPosition";
- public final static String SEARCH_SEND_QUERY = "DialogCursorProtocol.SEARCH.query";
- }
-
- /**
* Intent extra data key: Use this key with Intent.ACTION_SEARCH and
* {@link android.content.Intent#getStringExtra content.Intent.getStringExtra()}
* to obtain the action message that was defined for a particular search action key and/or
@@ -1421,40 +1354,6 @@
public final static String SHORTCUT_MIME_TYPE =
"vnd.android.cursor.item/vnd.android.search.suggest";
-
- /**
- * The authority of the provider to report clicks to when a click is detected after pivoting
- * into a specific app's search from global search.
- *
- * In addition to the columns below, the suggestion columns are used to pass along the full
- * suggestion so it can be shortcutted.
- *
- * @hide
- */
- public final static String SEARCH_CLICK_REPORT_AUTHORITY =
- "com.android.globalsearch.stats";
-
- /**
- * The path the write goes to.
- *
- * @hide
- */
- public final static String SEARCH_CLICK_REPORT_URI_PATH = "click";
-
- /**
- * The column storing the query for the click.
- *
- * @hide
- */
- public final static String SEARCH_CLICK_REPORT_COLUMN_QUERY = "query";
-
- /**
- * The column storing the component name of the application that was pivoted into.
- *
- * @hide
- */
- public final static String SEARCH_CLICK_REPORT_COLUMN_COMPONENT = "component";
-
/**
* Column name for suggestions cursor. <i>Unused - can be null or column can be omitted.</i>
*/
@@ -1531,10 +1430,7 @@
*/
public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data";
/**
- * Column name for suggestions cursor. <i>Optional.</i> This column allows suggestions
- * to provide additional arbitrary data which will be included as an extra under the key
- * {@link #COMPONENT_NAME_KEY}. For use by the global search system only - if other providers
- * attempt to use this column, the value will be overwritten by global search.
+ * TODO: Remove
*
* @hide
*/
@@ -1594,27 +1490,6 @@
public final static String SUGGEST_PARAMETER_LIMIT = "limit";
/**
- * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
- * the search dialog will switch to a different suggestion source when the
- * suggestion is clicked.
- *
- * {@link #SUGGEST_COLUMN_INTENT_DATA} must contain
- * the flattened {@link ComponentName} of the activity which is to be searched.
- *
- * TODO: Should {@link #SUGGEST_COLUMN_INTENT_DATA} instead contain a URI in the format
- * used by {@link android.provider.Applications}?
- *
- * TODO: This intent should be protected by the same permission that we use
- * for replacing the global search provider.
- *
- * The query text field will be set to the value of {@link #SUGGEST_COLUMN_QUERY}.
- *
- * @hide Pending API council approval.
- */
- public final static String INTENT_ACTION_CHANGE_SEARCH_SOURCE
- = "android.search.action.CHANGE_SEARCH_SOURCE";
-
- /**
* Intent action for starting the global search activity.
* The global search provider should handle this intent.
*
@@ -1663,7 +1538,7 @@
* @hide
*/
public final static String INTENT_ACTION_NONE = "android.search.action.ZILCH";
-
+
/**
* Reference to the shared system search service.
*/
@@ -1672,13 +1547,6 @@
private final Context mContext;
/**
- * compact representation of the activity associated with this search manager so
- * we can say who we are when starting search. the search managerservice, in turn,
- * uses this to properly handle the back stack.
- */
- private int mIdent;
-
- /**
* The package associated with this seach manager.
*/
private String mAssociatedPackage;
@@ -1696,21 +1564,6 @@
mService = ISearchManager.Stub.asInterface(
ServiceManager.getService(Context.SEARCH_SERVICE));
}
-
- /*package*/ boolean hasIdent() {
- return mIdent != 0;
- }
-
- /*package*/ void setIdent(int ident, ComponentName component) {
- if (mIdent != 0) {
- throw new IllegalStateException("mIdent already set");
- }
- if (component == null) {
- throw new IllegalArgumentException("component must be non-null");
- }
- mIdent = ident;
- mAssociatedPackage = component.getPackageName();
- }
/**
* Launch search UI.
@@ -1757,15 +1610,14 @@
ComponentName launchActivity,
Bundle appSearchData,
boolean globalSearch) {
- ensureSearchDialog();
-
if (globalSearch) {
startGlobalSearch(initialQuery, selectInitialQuery, appSearchData);
return;
}
- mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData,
- globalSearch);
+ ensureSearchDialog();
+
+ mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData);
}
private void ensureSearchDialog() {
@@ -1994,17 +1846,6 @@
return null;
}
}
-
- /**
- * Checks whether the given searchable is the default searchable.
- *
- * @hide because SearchableInfo is not part of the API.
- */
- public boolean isDefaultSearchable(SearchableInfo searchable) {
- SearchableInfo defaultSearchable = getSearchableInfo(null, true);
- return defaultSearchable != null
- && defaultSearchable.getSearchActivity().equals(searchable.getSearchActivity());
- }
/**
* Gets a cursor with search suggestions.
@@ -2091,56 +1932,4 @@
}
}
- /**
- * Returns a list of the searchable activities that handle web searches.
- *
- * @return a list of all searchable activities that handle
- * {@link android.content.Intent#ACTION_WEB_SEARCH}.
- *
- * @hide because SearchableInfo is not part of the API.
- */
- public List<SearchableInfo> getSearchablesForWebSearch() {
- try {
- return mService.getSearchablesForWebSearch();
- } catch (RemoteException e) {
- Log.e(TAG, "getSearchablesForWebSearch() failed: " + e);
- return null;
- }
- }
-
- /**
- * Returns the default searchable activity for web searches.
- *
- * @return searchable information for the activity handling web searches by default.
- *
- * @hide because SearchableInfo is not part of the API.
- */
- public SearchableInfo getDefaultSearchableForWebSearch() {
- try {
- return mService.getDefaultSearchableForWebSearch();
- } catch (RemoteException e) {
- Log.e(TAG, "getDefaultSearchableForWebSearch() failed: " + e);
- return null;
- }
- }
-
- /**
- * Sets the default searchable activity for web searches.
- *
- * @param component Name of the component to set as default activity for web searches.
- *
- * @hide
- */
- public void setDefaultWebSearch(ComponentName component) {
- try {
- mService.setDefaultWebSearch(component);
- } catch (RemoteException e) {
- Log.e(TAG, "setDefaultWebSearch() failed: " + e);
- }
- }
-
- private static void debug(String msg) {
- Thread thread = Thread.currentThread();
- Log.d(TAG, msg + " (" + thread.getName() + "-" + thread.getId() + ")");
- }
}
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 173c3e1..57795d1 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -16,7 +16,6 @@
package android.app;
-import android.app.SearchManager.DialogCursorProtocol;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -30,12 +29,10 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.net.Uri;
-import android.os.Bundle;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
-import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
@@ -65,7 +62,6 @@
private Context mProviderContext;
private WeakHashMap<String, Drawable.ConstantState> mOutsideDrawablesCache;
private SparseArray<Drawable.ConstantState> mBackgroundsCache;
- private boolean mGlobalSearchMode;
private boolean mClosed = false;
// Cached column indexes, updated when the cursor changes.
@@ -76,29 +72,8 @@
private int mIconName2Col;
private int mBackgroundColorCol;
- // The extra used to tell a cursor to close itself. This is a hack, see the description by
- // its use later in this file.
- private static final String EXTRA_CURSOR_RESPOND_CLOSE_CURSOR = "cursor_respond_close_cursor";
-
- // The bundle which contains {EXTRA_CURSOR_RESPOND_CLOSE_CURSOR=true}, just cached once
- // so we don't bother recreating it a bunch.
- private final Bundle mCursorRespondCloseCursorBundle;
-
- // This value is stored in SuggestionsAdapter by the SearchDialog to indicate whether
- // a particular list item should be selected upon the next call to notifyDataSetChanged.
- // This is used to indicate the index of the "More results..." list item so that when
- // the data set changes after a click of "More results...", we can correctly tell the
- // ListView to scroll to the right line item. It gets reset to NONE every time it
- // is consumed.
- private int mListItemToSelect = NONE;
static final int NONE = -1;
- // holds the maximum position that has been displayed to the user
- int mMaxDisplayed = NONE;
-
- // holds the position that, when displayed, should result in notifying the cursor
- int mDisplayNotifyPos = NONE;
-
private final Runnable mStartSpinnerRunnable;
private final Runnable mStopSpinnerRunnable;
@@ -110,8 +85,7 @@
public SuggestionsAdapter(Context context, SearchDialog searchDialog,
SearchableInfo searchable,
- WeakHashMap<String, Drawable.ConstantState> outsideDrawablesCache,
- boolean globalSearchMode) {
+ WeakHashMap<String, Drawable.ConstantState> outsideDrawablesCache) {
super(context,
com.android.internal.R.layout.search_dropdown_item_icons_2line,
null, // no initial cursor
@@ -126,7 +100,6 @@
mOutsideDrawablesCache = outsideDrawablesCache;
mBackgroundsCache = new SparseArray<Drawable.ConstantState>();
- mGlobalSearchMode = globalSearchMode;
mStartSpinnerRunnable = new Runnable() {
public void run() {
@@ -140,10 +113,6 @@
}
};
- // Create this once because we'll reuse it a bunch.
- mCursorRespondCloseCursorBundle = new Bundle();
- mCursorRespondCloseCursorBundle.putBoolean(EXTRA_CURSOR_RESPOND_CLOSE_CURSOR, true);
-
// delay 500ms when deleting
getFilter().setDelayer(new Filter.Delayer() {
@@ -177,27 +146,22 @@
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
if (DBG) Log.d(LOG_TAG, "runQueryOnBackgroundThread(" + constraint + ")");
String query = (constraint == null) ? "" : constraint.toString();
- if (!mGlobalSearchMode) {
- /**
- * for in app search we show the progress spinner until the cursor is returned with
- * the results. for global search we manage the progress bar using
- * {@link DialogCursorProtocol#POST_REFRESH_RECEIVE_ISPENDING}.
- */
- mSearchDialog.getWindow().getDecorView().post(mStartSpinnerRunnable);
- }
+ /**
+ * for in app search we show the progress spinner until the cursor is returned with
+ * the results.
+ */
+ mSearchDialog.getWindow().getDecorView().post(mStartSpinnerRunnable);
try {
final Cursor cursor = mSearchManager.getSuggestions(mSearchable, query, QUERY_LIMIT);
// trigger fill window so the spinner stays up until the results are copied over and
// closer to being ready
- if (!mGlobalSearchMode && cursor != null) cursor.getCount();
+ if (cursor != null) cursor.getCount();
return cursor;
} catch (RuntimeException e) {
Log.w(LOG_TAG, "Search suggestions query threw an exception.", e);
return null;
} finally {
- if (!mGlobalSearchMode) {
- mSearchDialog.getWindow().getDecorView().post(mStopSpinnerRunnable);
- }
+ mSearchDialog.getWindow().getDecorView().post(mStopSpinnerRunnable);
}
}
@@ -221,21 +185,8 @@
}
try {
- Cursor oldCursor = getCursor();
super.changeCursor(c);
-
- // We send a special respond to the cursor to tell it to close itself directly because
- // it may not happen correctly for some cursors currently. This was originally
- // included as a fix to http://b/2036290, in which the search dialog was holding
- // on to references to the web search provider unnecessarily. This is being caused by
- // the fact that the cursor is not being correctly closed in
- // BulkCursorToCursorAdapter#close, which remains unfixed (see http://b/2015069).
- //
- // TODO: Remove this hack once http://b/2015069 is fixed.
- if (oldCursor != null && oldCursor != c) {
- oldCursor.respond(mCursorRespondCloseCursorBundle);
- }
-
+
if (c != null) {
mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
@@ -249,79 +200,6 @@
}
}
- @Override
- public void notifyDataSetChanged() {
- if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged");
- super.notifyDataSetChanged();
-
- callCursorPostRefresh(mCursor);
-
- // look out for the pending item we are supposed to scroll to
- if (mListItemToSelect != NONE) {
- mSearchDialog.setListSelection(mListItemToSelect);
- mListItemToSelect = NONE;
- }
- }
-
- /**
- * Handle sending and receiving information associated with
- * {@link DialogCursorProtocol#POST_REFRESH}.
- *
- * @param cursor The cursor to call.
- */
- private void callCursorPostRefresh(Cursor cursor) {
- if (!mGlobalSearchMode) return;
- final Bundle request = new Bundle();
- request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.POST_REFRESH);
- final Bundle response = cursor.respond(request);
-
- mSearchDialog.setWorking(
- response.getBoolean(DialogCursorProtocol.POST_REFRESH_RECEIVE_ISPENDING, false));
-
- mDisplayNotifyPos =
- response.getInt(DialogCursorProtocol.POST_REFRESH_RECEIVE_DISPLAY_NOTIFY, -1);
- }
-
- /**
- * Tell the cursor which position was clicked, handling sending and receiving information
- * associated with {@link DialogCursorProtocol#CLICK}.
- *
- * @param cursor The cursor
- * @param position The position that was clicked.
- */
- void callCursorOnClick(Cursor cursor, int position, int actionKey, String actionMsg) {
- if (!mGlobalSearchMode) return;
- final Bundle request = new Bundle(5);
- request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
- request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
- request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
- if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
- request.putInt(DialogCursorProtocol.CLICK_SEND_ACTION_KEY, actionKey);
- request.putString(DialogCursorProtocol.CLICK_SEND_ACTION_MSG, actionMsg);
- }
- final Bundle response = cursor.respond(request);
- mMaxDisplayed = -1;
- mListItemToSelect = response.getInt(
- DialogCursorProtocol.CLICK_RECEIVE_SELECTED_POS, SuggestionsAdapter.NONE);
- }
-
- /**
- * Tell the cursor that a search was started without using a suggestion.
- *
- * @param query The search query.
- */
- void reportSearch(String query) {
- if (!mGlobalSearchMode) return;
- Cursor cursor = getCursor();
- if (cursor == null) return;
- final Bundle request = new Bundle(3);
- request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.SEARCH);
- request.putString(DialogCursorProtocol.SEARCH_SEND_QUERY, query);
- request.putInt(DialogCursorProtocol.SEARCH_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
- // the response is always empty
- cursor.respond(request);
- }
-
/**
* Tags the view with cached child view look-ups.
*/
@@ -353,20 +231,6 @@
@Override
public void bindView(View view, Context context, Cursor cursor) {
ChildViewCache views = (ChildViewCache) view.getTag();
- final int pos = cursor.getPosition();
-
- // update the maximum position displayed since last refresh
- if (pos > mMaxDisplayed) {
- mMaxDisplayed = pos;
- }
-
- // if the cursor wishes to be notified about this position, send it
- if (mGlobalSearchMode && mDisplayNotifyPos != NONE && pos == mDisplayNotifyPos) {
- final Bundle request = new Bundle();
- request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.THRESH_HIT);
- mCursor.respond(request);
- mDisplayNotifyPos = NONE; // only notify the first time
- }
int backgroundColor = 0;
if (mBackgroundColorCol != -1) {
diff --git a/core/java/android/backup/BackupDataInput.java b/core/java/android/backup/BackupDataInput.java
index 67d51ea..295dc66 100644
--- a/core/java/android/backup/BackupDataInput.java
+++ b/core/java/android/backup/BackupDataInput.java
@@ -133,7 +133,7 @@
/**
* Consume the current record's data without actually reading it into a buffer
- * for further processing. This allows a {@link android.backup.BackupAgent} to
+ * for further processing. This allows a {@link android.app.BackupAgent} to
* efficiently discard obsolete or otherwise uninteresting records during the
* restore operation.
*
diff --git a/core/java/android/backup/RestoreSession.java b/core/java/android/backup/RestoreSession.java
index fc53854..bc410c4 100644
--- a/core/java/android/backup/RestoreSession.java
+++ b/core/java/android/backup/RestoreSession.java
@@ -63,7 +63,7 @@
*
* @return Zero on success; nonzero on error. The observer will only receive
* progress callbacks if this method returned zero.
- * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+ * @param token The token from {@link #getAvailableRestoreSets()} corresponding to
* the restore set that should be used.
* @param observer If non-null, this binder points to an object that will receive
* progress callbacks during the restore operation.
@@ -120,8 +120,7 @@
* object is no longer valid.
*
* <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session,
- * even if {@link #getAvailableRestoreSets()} or
- * {@link #restorePackage(long, String, RestoreObserver)} failed.
+ * even if {@link #restorePackage(String, RestoreObserver)} failed.
*/
public void endRestoreSession() {
try {
diff --git a/core/java/android/gesture/Learner.java b/core/java/android/gesture/Learner.java
index 60997e0..a105652 100755
--- a/core/java/android/gesture/Learner.java
+++ b/core/java/android/gesture/Learner.java
@@ -72,7 +72,8 @@
for (int i = 0; i < count; i++) {
final Instance instance = instances.get(i);
// the label can be null, as specified in Instance
- if ((instance.label == null && name == null) || instance.label.equals(name)) {
+ if ((instance.label == null && name == null)
+ || (instance.label != null && instance.label.equals(name))) {
toDelete.add(instance);
}
}
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/BluetoothService.java b/core/java/android/server/BluetoothService.java
index dfb775f..aa20ac4 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -136,6 +136,14 @@
}
return false;
}
+
+ @Override
+ public int hashCode() {
+ int hash = 1;
+ hash = hash * 31 + (address == null ? 0 : address.hashCode());
+ hash = hash * 31 + (uuid == null ? 0 : uuid.hashCode());
+ return hash;
+ }
}
static {
diff --git a/core/java/android/text/AndroidCharacter.java b/core/java/android/text/AndroidCharacter.java
index af93b5d..05887c5 100644
--- a/core/java/android/text/AndroidCharacter.java
+++ b/core/java/android/text/AndroidCharacter.java
@@ -73,6 +73,11 @@
* Replace the specified slice of <code>text</code> with the chars'
* right-to-left mirrors (if any), returning true if any
* replacements were made.
+ *
+ * @param text array of characters to apply mirror operation
+ * @param start first character in array to mirror
+ * @param count maximum number of characters to mirror
+ * @return true if replacements were made
*/
public native static boolean mirror(char[] text, int start, int count);
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
index 6635ddb8..f320701 100644
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ b/core/java/android/text/style/LeadingMarginSpan.java
@@ -45,7 +45,7 @@
/**
* Renders the leading margin. This is called before the margin has been
- * adjusted by the value returned by {@link getLeadingMargin(boolean)}.
+ * 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.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 57fdd8b..bc49439 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1504,6 +1504,31 @@
* @hide
*/
private static final int PREPRESSED = 0x02000000;
+
+ /**
+ * Always allow a user to overscroll this view, provided it is a
+ * view that can scroll.
+ */
+ private static final int OVERSCROLL_ALWAYS = 0;
+
+ /**
+ * Allow a user to overscroll this view only if the content is large
+ * enough to meaningfully scroll, provided it is a view that can scroll.
+ */
+ private static final int OVERSCROLL_IF_CONTENT_SCROLLS = 1;
+
+ /**
+ * Never allow a user to overscroll this view.
+ */
+ private static final int OVERSCROLL_NEVER = 2;
+
+ /**
+ * Controls the overscroll mode for this view.
+ * See {@link #overscrollBy(int, int, int, int, int, int, int, int)},
+ * {@link #OVERSCROLL_ALWAYS}, {@link #OVERSCROLL_IF_CONTENT_SCROLLS},
+ * and {@link #OVERSCROLL_NEVER}.
+ */
+ private int mOverscrollMode = OVERSCROLL_ALWAYS;
/**
* The parent this view is attached to.
@@ -2053,6 +2078,9 @@
});
}
break;
+ case R.styleable.View_overscrollMode:
+ mOverscrollMode = a.getInt(attr, OVERSCROLL_ALWAYS);
+ break;
}
}
@@ -3022,6 +3050,7 @@
*
* @param enabled True if this view is enabled, false otherwise.
*/
+ @RemotableViewMethod
public void setEnabled(boolean enabled) {
if (enabled == isEnabled()) return;
@@ -8573,43 +8602,59 @@
int scrollX, int scrollY,
int scrollRangeX, int scrollRangeY,
int maxOverscrollX, int maxOverscrollY) {
- // Scale the scroll amount if we're in the dropoff zone
- final int dropoffX = maxOverscrollX / 2;
- final int dropoffLeft = -dropoffX;
- final int dropoffRight = dropoffX + scrollRangeX;
- int newScrollX;
- if ((scrollX < dropoffLeft && deltaX < 0) ||
- (scrollX > dropoffRight && deltaX > 0)) {
- newScrollX = scrollX + deltaX / 2;
- } else {
- newScrollX = scrollX + deltaX;
- if (newScrollX > dropoffRight && deltaX > 0) {
- int extra = newScrollX - dropoffRight;
- newScrollX = dropoffRight + extra / 2;
- } else if (newScrollX < dropoffLeft && deltaX < 0) {
- int extra = newScrollX - dropoffLeft;
- newScrollX = dropoffLeft + extra / 2;
- }
- }
+ final int overscrollMode = mOverscrollMode;
+ final boolean canScrollHorizontal =
+ computeHorizontalScrollRange() > computeHorizontalScrollExtent();
+ final boolean canScrollVertical =
+ computeVerticalScrollRange() > computeVerticalScrollExtent();
+ final boolean overscrollHorizontal = overscrollMode == OVERSCROLL_ALWAYS ||
+ (overscrollMode == OVERSCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
+ final boolean overscrollVertical = overscrollMode == OVERSCROLL_ALWAYS ||
+ (overscrollMode == OVERSCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
- final int dropoffY = maxOverscrollY / 2;
- final int dropoffTop = -dropoffY;
- final int dropoffBottom = dropoffY + scrollRangeY;
- int newScrollY;
- if ((scrollY < dropoffTop && deltaY < 0) ||
- (scrollY > dropoffBottom && deltaY > 0)) {
- newScrollY = scrollY + deltaY / 2;
- } else {
- newScrollY = scrollY + deltaY;
- if (newScrollY > dropoffBottom && deltaY > 0) {
- int extra = newScrollY - dropoffBottom;
- newScrollY = dropoffBottom + extra / 2;
- } else if (newScrollY < dropoffTop && deltaY < 0) {
- int extra = newScrollY - dropoffTop;
- newScrollY = dropoffTop + extra / 2;
+ int newScrollX = scrollX + deltaX;
+ if (overscrollHorizontal) {
+ // Scale the scroll amount if we're in the dropoff zone
+ final int dropoffX = maxOverscrollX / 2;
+ final int dropoffLeft = -dropoffX;
+ final int dropoffRight = dropoffX + scrollRangeX;
+ if ((scrollX < dropoffLeft && deltaX < 0) ||
+ (scrollX > dropoffRight && deltaX > 0)) {
+ newScrollX = scrollX + deltaX / 2;
+ } else {
+ if (newScrollX > dropoffRight && deltaX > 0) {
+ int extra = newScrollX - dropoffRight;
+ newScrollX = dropoffRight + extra / 2;
+ } else if (newScrollX < dropoffLeft && deltaX < 0) {
+ int extra = newScrollX - dropoffLeft;
+ newScrollX = dropoffLeft + extra / 2;
+ }
}
+ } else {
+ maxOverscrollX = 0;
}
+ int newScrollY = scrollY + deltaY;
+ if (overscrollVertical) {
+ final int dropoffY = maxOverscrollY / 2;
+ final int dropoffTop = -dropoffY;
+ final int dropoffBottom = dropoffY + scrollRangeY;
+ if ((scrollY < dropoffTop && deltaY < 0) ||
+ (scrollY > dropoffBottom && deltaY > 0)) {
+ newScrollY = scrollY + deltaY / 2;
+ } else {
+ if (newScrollY > dropoffBottom && deltaY > 0) {
+ int extra = newScrollY - dropoffBottom;
+ newScrollY = dropoffBottom + extra / 2;
+ } else if (newScrollY < dropoffTop && deltaY < 0) {
+ int extra = newScrollY - dropoffTop;
+ newScrollY = dropoffTop + extra / 2;
+ }
+ }
+ } else {
+ maxOverscrollY = 0;
+ }
+
// Clamp values if at the limits and record
final int left = -maxOverscrollX;
final int right = maxOverscrollX + scrollRangeX;
@@ -8636,8 +8681,8 @@
// Bump the device with some haptic feedback if we're at the edge
// and didn't start there.
- if ((clampedX && scrollX != left && scrollX != right) ||
- (clampedY && scrollY != top && scrollY != bottom)) {
+ if ((overscrollHorizontal && clampedX && scrollX != left && scrollX != right) ||
+ (overscrollVertical && clampedY && scrollY != top && scrollY != bottom)) {
performHapticFeedback(HapticFeedbackConstants.SCROLL_BARRIER);
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index acb64aa..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 {
@@ -3759,6 +3767,7 @@
}
return true;
}
+ clearTextEntry(true);
nativeSetFollowedLink(true);
if (!mCallbackProxy.uiOverrideUrlLoading(nativeCursorText())) {
mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
@@ -3839,7 +3848,7 @@
@Override
protected void onDetachedFromWindow() {
- clearTextEntry();
+ clearTextEntry(false);
super.onDetachedFromWindow();
// Clean up the zoom controller
mZoomButtonsController.setVisible(false);
@@ -5826,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();
@@ -5948,7 +5957,7 @@
}
break;
case CLEAR_TEXT_ENTRY:
- clearTextEntry();
+ clearTextEntry(false);
break;
case INVAL_RECT_MSG_ID: {
Rect r = (Rect)msg.obj;
@@ -6555,8 +6564,7 @@
*/
private void sendMoveMouseIfLatest(boolean removeFocus) {
if (removeFocus) {
- clearTextEntry();
- setFocusControllerInactive();
+ clearTextEntry(true);
}
mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE_IF_LATEST,
cursorData());
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 4c77bdc..a79bbee 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2364,7 +2364,16 @@
public void draw(Canvas canvas) {
super.draw(canvas);
if (mFastScroller != null) {
- mFastScroller.draw(canvas);
+ final int scrollY = mScrollY;
+ if (scrollY != 0) {
+ // Pin the fast scroll thumb to the top/bottom during overscroll.
+ int restoreCount = canvas.save();
+ canvas.translate(0, (float) scrollY);
+ mFastScroller.draw(canvas);
+ canvas.restoreToCount(restoreCount);
+ } else {
+ mFastScroller.draw(canvas);
+ }
}
}
@@ -2589,7 +2598,8 @@
if (trackMotionScroll(delta, delta)) {
if (motionView != null) {
// Tweak the scroll for how far we overshot
- mScrollY -= delta - (motionView.getTop() - oldTop);
+ int overshoot = -(delta - (motionView.getTop() - oldTop));
+ overscrollBy(0, overshoot, 0, mScrollY, 0, 0, 0, getOverscrollMax());
}
float vel = scroller.getCurrVelocity();
if (delta > 0) {
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 3853359..233ce30 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -32,6 +32,7 @@
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.RemotableViewMethod;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -69,6 +70,7 @@
private ColorFilter mColorFilter;
private int mAlpha = 255;
private int mViewAlphaScale = 256;
+ private boolean mColorMod = false;
private Drawable mDrawable = null;
private int[] mState = null;
@@ -138,7 +140,7 @@
int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0);
if (tint != 0) {
- setColorFilter(tint, PorterDuff.Mode.SRC_ATOP);
+ setColorFilter(tint);
}
mCropToPadding = a.getBoolean(
@@ -877,6 +879,18 @@
setColorFilter(new PorterDuffColorFilter(color, mode));
}
+ /**
+ * Set a tinting option for the image. Assumes
+ * {@link PorterDuff.Mode#SRC_ATOP} blending mode.
+ *
+ * @param color Color tint to apply.
+ * @attr ref android.R.styleable#ImageView_tint
+ */
+ @RemotableViewMethod
+ public final void setColorFilter(int color) {
+ setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+ }
+
public final void clearColorFilter() {
setColorFilter(null);
}
@@ -889,22 +903,29 @@
public void setColorFilter(ColorFilter cf) {
if (mColorFilter != cf) {
mColorFilter = cf;
+ mColorMod = true;
applyColorMod();
invalidate();
}
}
+ @RemotableViewMethod
public void setAlpha(int alpha) {
alpha &= 0xFF; // keep it legal
if (mAlpha != alpha) {
mAlpha = alpha;
+ mColorMod = true;
applyColorMod();
invalidate();
}
}
private void applyColorMod() {
- if (mDrawable != null) {
+ // Only mutate and apply when modifications have occurred. This should
+ // not reset the mColorMod flag, since these filters need to be
+ // re-applied if the Drawable is changed.
+ if (mDrawable != null && mColorMod) {
+ mDrawable = mDrawable.mutate();
mDrawable.setColorFilter(mColorFilter);
mDrawable.setAlpha(mAlpha * mViewAlphaScale >> 8);
}
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index aee25b0..8034961 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -38,7 +38,7 @@
@RemoteView
public class ViewFlipper extends ViewAnimator {
private static final String TAG = "ViewFlipper";
- private static final boolean LOGD = true;
+ private static final boolean LOGD = false;
private static final int DEFAULT_INTERVAL = 3000;
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 1353478..5d8d419 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -165,7 +165,8 @@
goto MIRROR_END;
}
- if (start > start + count || env->GetArrayLength(charArray) < count) {
+ if (start < 0 || start > start + count
+ || env->GetArrayLength(charArray) < start + count) {
jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
goto MIRROR_END;
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0f6a5c1..ff93984 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1307,6 +1307,19 @@
<code>public void sayHello(View v)</code> method of your context
(typically, your Activity). -->
<attr name="onClick" format="string" />
+
+ <!-- Defines overscrolling behavior. This property is used only if the
+ View is scrollable. Overscrolling is the ability for the user to
+ scroll a View beyond its content boundaries into empty space. -->
+ <attr name="overscrollMode">
+ <!-- Always allow the user to overscroll the content. -->
+ <enum name="always" value="0" />
+ <!-- Only allow the user to overscroll content if the content is large
+ enough to meaningfully scroll. -->
+ <enum name="ifContentScrolls" value="1" />
+ <!-- Never overscroll. -->
+ <enum name="never" value="2" />
+ </attr>
</declare-styleable>
<!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
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 aca220f..b334337 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1227,10 +1227,10 @@
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="webTextViewStyle" id="0x010102ba" />
+ <public type="attr" name="installLocation" id="0x010102b7" />
+ <public type="attr" name="safeMode" id="0x010102b8" />
+ <public type="attr" name="webTextViewStyle" id="0x010102b9" />
+ <public type="attr" name="overscrollMode" id="0x010102ba" />
<public type="anim" name="cycle_interpolator" id="0x010a000c" />
diff --git a/core/tests/coretests/src/android/app/SearchManagerTest.java b/core/tests/coretests/src/android/app/SearchManagerTest.java
index fc7e787..08b7f60 100644
--- a/core/tests/coretests/src/android/app/SearchManagerTest.java
+++ b/core/tests/coretests/src/android/app/SearchManagerTest.java
@@ -120,23 +120,6 @@
assertSame(searchManager1, searchManager2 );
}
- @MediumTest
- public void testSearchables() {
- SearchManager searchManager = (SearchManager)
- mContext.getSystemService(Context.SEARCH_SERVICE);
- SearchableInfo si;
-
- si = searchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, false);
- assertNotNull(si);
- assertFalse(searchManager.isDefaultSearchable(si));
- si = searchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, true);
- assertNotNull(si);
- assertTrue(searchManager.isDefaultSearchable(si));
- si = searchManager.getSearchableInfo(null, true);
- assertNotNull(si);
- assertTrue(searchManager.isDefaultSearchable(si));
- }
-
/**
* Tests that startSearch() can be called multiple times without stopSearch()
* in between.
diff --git a/core/tests/hosttests/Android.mk b/core/tests/hosttests/Android.mk
new file mode 100644
index 0000000..0001201
--- /dev/null
+++ b/core/tests/hosttests/Android.mk
@@ -0,0 +1,32 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+#LOCAL_TEST_TYPE := hostSideOnly
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := FrameworkCoreHostTests
+
+LOCAL_JAVA_LIBRARIES := hosttestlib ddmlib junit
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/core/tests/hosttests/README b/core/tests/hosttests/README
new file mode 100644
index 0000000..d3bdb83
--- /dev/null
+++ b/core/tests/hosttests/README
@@ -0,0 +1,6 @@
+This dir contains tests which run on a host machine, and test aspects of
+package install etc via adb.
+
+To run, do:
+runtest framework-core-host
+
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java
new file mode 100644
index 0000000..9c9d777
--- /dev/null
+++ b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTests.java
@@ -0,0 +1,216 @@
+/*
+ * 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 android.content.pm;
+
+import com.android.ddmlib.IShellOutputReceiver;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.MultiLineReceiver;
+import com.android.ddmlib.SyncService;
+import com.android.ddmlib.SyncService.ISyncProgressMonitor;
+import com.android.ddmlib.SyncService.SyncResult;
+import com.android.hosttest.DeviceTestCase;
+import com.android.hosttest.DeviceTestSuite;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.Test;
+
+/**
+ * Set of tests that verify host side install cases
+ */
+public class PackageManagerHostTests extends DeviceTestCase {
+
+ // testPushAppPrivate constants
+ // these constants must match values defined in test-apps/SimpleTestApp
+ private static final String SIMPLE_APK = "SimpleTestApp.apk";
+ private static final String SIMPLE_PKG = "com.android.framework.simpletestapp";
+ // TODO: get this value from Android Environment instead of hardcoding
+ private static final String APP_PRIVATE_PATH = "/data/app-private/";
+
+ private static final String LOG_TAG = "PackageManagerHostTests";
+
+ private static final int MAX_WAIT_FOR_DEVICE_TIME = 120 * 1000;
+ private static final int WAIT_FOR_DEVICE_POLL_TIME = 10 * 1000;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // ensure apk path has been set before test is run
+ assertNotNull(getTestAppPath());
+ }
+
+ /**
+ * Regression test to verify that pushing an apk to the private app directory doesn't install
+ * the app, and otherwise cause the system to blow up.
+ * <p/>
+ * Assumes adb is running as root in device under test.
+ */
+ public void testPushAppPrivate() throws IOException, InterruptedException {
+ Log.i(LOG_TAG, "testing pushing an apk to /data/app-private");
+ final String apkAppPrivatePath = APP_PRIVATE_PATH + SIMPLE_APK;
+
+ // cleanup test app just in case it was accidently installed
+ getDevice().uninstallPackage(SIMPLE_PKG);
+ executeShellCommand("stop");
+ pushFile(getTestAppFilePath(SIMPLE_APK), apkAppPrivatePath);
+ // sanity check to make sure file is there
+ assertTrue(doesRemoteFileExist(apkAppPrivatePath));
+ executeShellCommand("start");
+
+ waitForDevice();
+
+ // grep for package to make sure its not installed
+ assertFalse(doesPackageExist(SIMPLE_PKG));
+ // ensure it has been deleted from app-private
+ assertFalse(doesRemoteFileExist(apkAppPrivatePath));
+ }
+
+ /**
+ * Helper method to push a file to device
+ * @param apkAppPrivatePath
+ * @throws IOException
+ */
+ private void pushFile(final String localFilePath, final String destFilePath)
+ throws IOException {
+ SyncResult result = getDevice().getSyncService().pushFile(
+ localFilePath, destFilePath,
+ new NullSyncProgressMonitor());
+ assertEquals(SyncService.RESULT_OK, result.getCode());
+ }
+
+ /**
+ * Helper method to determine if file on device exists.
+ *
+ * @param destPath the absolute path of file on device to check
+ * @return <code>true</code> if file exists, <code>false</code> otherwise.
+ * @throws IOException if adb shell command failed
+ */
+ private boolean doesRemoteFileExist(String destPath) throws IOException {
+ String lsGrep = executeShellCommand(String.format("ls %s",
+ destPath));
+ return !lsGrep.contains("No such file or directory");
+ }
+
+ /**
+ * Helper method to determine if package on device exists.
+ *
+ * @param packageName the Android manifest package to check.
+ * @return <code>true</code> if package exists, <code>false</code> otherwise
+ * @throws IOException if adb shell command failed
+ */
+ private boolean doesPackageExist(String packageName) throws IOException {
+ String pkgGrep = executeShellCommand(String.format("pm path %s",
+ packageName));
+ return pkgGrep.contains("package:");
+ }
+
+ /**
+ * Waits for device's package manager to respond.
+ *
+ * @throws InterruptedException
+ * @throws IOException
+ */
+ private void waitForDevice() throws InterruptedException, IOException {
+ Log.i(LOG_TAG, "waiting for device");
+ int currentWaitTime = 0;
+ // poll the package manager until it returns something for android
+ while (!doesPackageExist("android")) {
+ Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
+ currentWaitTime += WAIT_FOR_DEVICE_POLL_TIME;
+ if (currentWaitTime > MAX_WAIT_FOR_DEVICE_TIME) {
+ Log.e(LOG_TAG, "time out waiting for device");
+ throw new InterruptedException();
+ }
+ }
+ }
+
+ /**
+ * Helper method which executes a adb shell command and returns output as a {@link String}
+ * @return
+ * @throws IOException
+ */
+ private String executeShellCommand(String command) throws IOException {
+ Log.d(LOG_TAG, String.format("adb shell %s", command));
+ CollectingOutputReceiver receiver = new CollectingOutputReceiver();
+ getDevice().executeShellCommand(command, receiver);
+ String output = receiver.getOutput();
+ Log.d(LOG_TAG, String.format("Result: %s", output));
+ return output;
+ }
+
+ /**
+ * Get the absolute file system location of test app with given filename
+ * @param fileName the file name of the test app apk
+ * @return {@link String} of absolute file path
+ */
+ private String getTestAppFilePath(String fileName) {
+ return String.format("%s%s%s", getTestAppPath(), File.separator, fileName);
+ }
+
+ public static Test suite() {
+ return new DeviceTestSuite(PackageManagerHostTests.class);
+ }
+
+ /**
+ * A {@link IShellOutputReceiver} which collects the whole shell output into one {@link String}
+ */
+ private static class CollectingOutputReceiver extends MultiLineReceiver {
+
+ private StringBuffer mOutputBuffer = new StringBuffer();
+
+ public String getOutput() {
+ return mOutputBuffer.toString();
+ }
+
+ @Override
+ public void processNewLines(String[] lines) {
+ for (String line: lines) {
+ mOutputBuffer.append(line);
+ mOutputBuffer.append("\n");
+ }
+ }
+
+ public boolean isCancelled() {
+ return false;
+ }
+ }
+
+ private static class NullSyncProgressMonitor implements ISyncProgressMonitor {
+ public void advance(int work) {
+ // ignore
+ }
+
+ public boolean isCanceled() {
+ // ignore
+ return false;
+ }
+
+ public void start(int totalWork) {
+ // ignore
+
+ }
+
+ public void startSubTask(String name) {
+ // ignore
+ }
+
+ public void stop() {
+ // ignore
+ }
+ }
+}
diff --git a/core/tests/hosttests/test-apps/Android.mk b/core/tests/hosttests/test-apps/Android.mk
new file mode 100644
index 0000000..e25764f
--- /dev/null
+++ b/core/tests/hosttests/test-apps/Android.mk
@@ -0,0 +1,21 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/core/tests/hosttests/test-apps/SimpleTestApp/Android.mk b/core/tests/hosttests/test-apps/SimpleTestApp/Android.mk
new file mode 100644
index 0000000..82543aa
--- /dev/null
+++ b/core/tests/hosttests/test-apps/SimpleTestApp/Android.mk
@@ -0,0 +1,27 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := SimpleTestApp
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/hosttests/test-apps/SimpleTestApp/AndroidManifest.xml b/core/tests/hosttests/test-apps/SimpleTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..ae36fe7
--- /dev/null
+++ b/core/tests/hosttests/test-apps/SimpleTestApp/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.framework.simpletestapp">
+
+ <!--
+ A simple empty app used to test various install scenarios/
+ -->
+
+</manifest>
diff --git a/core/tests/hosttests/test-apps/SimpleTestApp/src/com/android/framework/simpletestapp/SimpleAppActivity.java b/core/tests/hosttests/test-apps/SimpleTestApp/src/com/android/framework/simpletestapp/SimpleAppActivity.java
new file mode 100644
index 0000000..b7bbf94
--- /dev/null
+++ b/core/tests/hosttests/test-apps/SimpleTestApp/src/com/android/framework/simpletestapp/SimpleAppActivity.java
@@ -0,0 +1,25 @@
+/*
+ * 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.framework.simpletestapp;
+
+import android.app.Activity;
+
+/**
+ * Empty activity, not needed for this test
+ */
+public class SimpleAppActivity extends Activity {
+
+}
diff --git a/graphics/java/android/graphics/AvoidXfermode.java b/graphics/java/android/graphics/AvoidXfermode.java
index 2ed042b..7e2722d 100644
--- a/graphics/java/android/graphics/AvoidXfermode.java
+++ b/graphics/java/android/graphics/AvoidXfermode.java
@@ -38,15 +38,15 @@
*
* There are two modes, and each mode interprets a tolerance value.
*
- * AVOID: In this mode, drawing is allowed only on destination pixels that
+ * Avoid: In this mode, drawing is allowed only on destination pixels that
* are different from the op-color.
- * Tolerance near 0: avoid anything close to the op-color
- * Tolerance near 255: avoid only colors very close to the op-color
- *
- * TARGET: In this mode, drawing only occurs on destination pixels that
+ * Tolerance near 0: avoid any colors even remotely similar to the op-color
+ * Tolerance near 255: avoid only colors nearly identical to the op-color
+
+ * Target: In this mode, drawing only occurs on destination pixels that
* are similar to the op-color
- * Tolerance near 0: draw on colors that are very close to op-color
- * Tolerance near 255: draw on colors that to the op-color
+ * Tolerance near 0: draw only on colors that are nearly identical to the op-color
+ * Tolerance near 255: draw on any colors even remotely similar to the op-color
*/
public AvoidXfermode(int opColor, int tolerance, Mode mode) {
if (tolerance < 0 || tolerance > 255) {
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index b1d588e..b94df84 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -238,7 +238,10 @@
final int count = sets.length;
mStateListState.mStateSets = new int[count][];
for (int i = 0; i < count; i++) {
- mStateListState.mStateSets[i] = sets[i].clone();
+ final int[] set = sets[i];
+ if (set != null) {
+ mStateListState.mStateSets[i] = set.clone();
+ }
}
mMutated = true;
}
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 2bcad5b..925fd06 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <utils/Vector.h>
-#include <binder/Parcel.h>
#include <ui/Rect.h>
@@ -39,7 +38,6 @@
Region();
Region(const Region& rhs);
explicit Region(const Rect& rhs);
- explicit Region(const Parcel& parcel);
explicit Region(const void* buffer);
~Region();
@@ -118,10 +116,6 @@
// be sorted in Y and X and must not make the region invalid.
void addRectUnchecked(int l, int t, int r, int b);
- // flatten/unflatten a region to/from a Parcel
- status_t write(Parcel& parcel) const;
- status_t read(const Parcel& parcel);
-
// flatten/unflatten a region to/from a raw buffer
ssize_t write(void* buffer, size_t size) const;
static ssize_t writeEmpty(void* buffer, size_t size);
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 207ad15..6288bc4 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -34,6 +34,12 @@
Element::~Element()
{
+ for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) {
+ if (mRSC->mStateElement.mElements[ct] == this) {
+ mRSC->mStateElement.mElements.removeAt(ct);
+ break;
+ }
+ }
clear();
}
@@ -78,27 +84,62 @@
}
-Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
+const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
bool isNorm, uint32_t vecSize)
{
+ // Look for an existing match.
+ for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
+ const Element *ee = rsc->mStateElement.mElements[ct];
+ if (!ee->getFieldCount() &&
+ (ee->getComponent().getType() == dt) &&
+ (ee->getComponent().getKind() == dk) &&
+ (ee->getComponent().getIsNormalized() == isNorm) &&
+ (ee->getComponent().getVectorSize() == vecSize)) {
+ // Match
+ ee->incUserRef();
+ return ee;
+ }
+ }
+
Element *e = new Element(rsc);
e->mComponent.set(dt, dk, isNorm, vecSize);
e->mBits = e->mComponent.getBits();
+ rsc->mStateElement.mElements.push(e);
return e;
}
-Element * Element::create(Context *rsc, size_t count, const Element **ein,
+const Element * Element::create(Context *rsc, size_t count, const Element **ein,
const char **nin, const size_t * lengths)
{
+ // Look for an existing match.
+ for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
+ const Element *ee = rsc->mStateElement.mElements[ct];
+ if (ee->getFieldCount() == count) {
+ bool match = true;
+ for (uint32_t i=0; i < count; i++) {
+ if ((ee->mFields[i].e.get() != ein[i]) ||
+ (ee->mFields[i].name.length() != lengths[i]) ||
+ (ee->mFields[i].name != nin[i])) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ ee->incUserRef();
+ return ee;
+ }
+ }
+ }
+
Element *e = new Element(rsc);
e->mFields = new ElementField_t [count];
e->mFieldCount = count;
-
for (size_t ct=0; ct < count; ct++) {
e->mFields[ct].e.set(ein[ct]);
e->mFields[ct].name.setTo(nin[ct], lengths[ct]);
}
+ rsc->mStateElement.mElements.push(e);
return e;
}
@@ -168,6 +209,7 @@
ElementState::~ElementState()
{
+ rsAssert(!mElements.size());
}
@@ -184,9 +226,9 @@
uint32_t vecSize)
{
//LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize);
- Element *e = Element::create(rsc, dt, dk, norm, vecSize);
+ const Element *e = Element::create(rsc, dt, dk, norm, vecSize);
e->incUserRef();
- return e;
+ return (RsElement)e;
}
RsElement rsi_ElementCreate2(Context *rsc,
@@ -196,9 +238,9 @@
const size_t * nameLengths)
{
//LOGE("rsi_ElementCreate2 %i", count);
- Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths);
+ const Element *e = Element::create(rsc, count, (const Element **)ein, names, nameLengths);
e->incUserRef();
- return e;
+ return (RsElement)e;
}
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index 777e8ee..02a1ca2 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -60,9 +60,9 @@
void dumpLOGV(const char *prefix) const;
- static Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
+ static const Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
bool isNorm, uint32_t vecSize);
- static Element * create(Context *rsc, size_t count, const Element **,
+ static const Element * create(Context *rsc, size_t count, const Element **,
const char **, const size_t * lengths);
protected:
@@ -89,6 +89,8 @@
ElementState();
~ElementState();
+ // Cache of all existing elements.
+ Vector<const Element *> mElements;
};
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 89c5b00..677413e 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -191,6 +191,7 @@
LOGV("Dumping all objects");
const ObjectBase * o = rsc->mObjHead;
while (o) {
+ LOGV(" Object %p", o);
o->dumpLOGV(" ");
o = o->mNext;
}
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index f247022..bb03b87 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -56,6 +56,7 @@
protected:
const char *mAllocFile;
uint32_t mAllocLine;
+ Context *mRSC;
private:
void add() const;
@@ -64,7 +65,6 @@
bool checkDelete() const;
char * mName;
- Context *mRSC;
mutable int32_t mSysRefCount;
mutable int32_t mUserRefCount;
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 28f13d4..a2b2df4 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -364,7 +364,7 @@
void ProgramVertexState::init(Context *rsc, int32_t w, int32_t h)
{
- RsElement e = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
+ RsElement e = (RsElement) Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
rsi_TypeBegin(rsc, e);
rsi_TypeAdd(rsc, RS_DIMENSION_X, 48);
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 22a267a..9d24c6c 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -31,6 +31,12 @@
Type::~Type()
{
+ for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
+ if (mRSC->mStateType.mTypes[ct] == this) {
+ mRSC->mStateType.mTypes.removeAt(ct);
+ break;
+ }
+ }
if (mLODs) {
delete [] mLODs;
}
@@ -341,6 +347,18 @@
{
TypeState * stc = &rsc->mStateType;
+ for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
+ Type *t = stc->mTypes[ct];
+ if (t->getElement() != stc->mElement.get()) continue;
+ if (t->getDimX() != stc->mX) continue;
+ if (t->getDimY() != stc->mY) continue;
+ if (t->getDimZ() != stc->mZ) continue;
+ if (t->getDimLOD() != stc->mLOD) continue;
+ if (t->getDimFaces() != stc->mFaces) continue;
+ t->incUserRef();
+ return t;
+ }
+
Type * st = new Type(rsc);
st->incUserRef();
st->setDimX(stc->mX);
@@ -351,7 +369,7 @@
st->setDimFaces(stc->mFaces);
st->compute();
stc->mElement.clear();
-
+ stc->mTypes.push(st);
return st;
}
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 4fa4933..28e6274 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -137,6 +137,10 @@
uint32_t mLOD;
bool mFaces;
ObjectBaseRef<const Element> mElement;
+
+
+ // Cache of all existing types.
+ Vector<Type *> mTypes;
};
diff --git a/libs/surfaceflinger_client/LayerState.cpp b/libs/surfaceflinger_client/LayerState.cpp
index 114a9e9..01c4c7e 100644
--- a/libs/surfaceflinger_client/LayerState.cpp
+++ b/libs/surfaceflinger_client/LayerState.cpp
@@ -22,17 +22,37 @@
status_t layer_state_t::write(Parcel& output) const
{
+ status_t err;
+
+ size_t len = transparentRegion.write(NULL, 0);
+ err = output.writeInt32(len);
+ if (err < NO_ERROR) return err;
+
+ void* buf = output.writeInplace(len);
+ if (buf == NULL) return NO_MEMORY;
+
+ err = transparentRegion.write(buf, len);
+ if (err < NO_ERROR) return err;
+
+ // NOTE: regions are at the end of the structure
size_t size = sizeof(layer_state_t);
- transparentRegion.write(output);
size -= sizeof(transparentRegion);
- output.write(this, size);
- return NO_ERROR;
+ err = output.write(this, size);
+ return err;
}
status_t layer_state_t::read(const Parcel& input)
{
+ status_t err;
+ size_t len = input.readInt32();
+ void const* buf = input.readInplace(len);
+ if (buf == NULL) return NO_MEMORY;
+
+ err = transparentRegion.read(buf);
+ if (err < NO_ERROR) return err;
+
+ // NOTE: regions are at the end of the structure
size_t size = sizeof(layer_state_t);
- transparentRegion.read(input);
size -= sizeof(transparentRegion);
input.read(this, size);
return NO_ERROR;
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index d21ed57..12db908 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -63,16 +63,10 @@
{
}
-Region::Region(const Parcel& parcel)
-{
- status_t err = read(parcel);
- LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
-}
-
Region::Region(const void* buffer)
{
status_t err = read(buffer);
- LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
+ LOGE_IF(err<0, "error %s reading Region from buffer", strerror(err));
}
Region::~Region()
@@ -532,37 +526,6 @@
// ----------------------------------------------------------------------------
-status_t Region::write(Parcel& parcel) const
-{
-#if VALIDATE_REGIONS
- validate(*this, "write(Parcel)");
-#endif
- status_t err;
- const size_t count = mStorage.size();
- const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
- void* buffer = parcel.writeInplace(sizeNeeded);
- if (!buffer) return NO_MEMORY;
- ssize_t written = Region::write(buffer, sizeNeeded);
- if (written < 0) return status_t(written);
- return NO_ERROR;
-}
-
-status_t Region::read(const Parcel& parcel)
-{
- void const* buffer = parcel.readInplace(sizeof(int32_t));
- if (!buffer) return NO_MEMORY;
- const size_t count = *static_cast<int32_t const *>(buffer);
- void const* dummy = parcel.readInplace((1+count)*sizeof(Rect));
- if (!dummy) return NO_MEMORY;
- const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
- const ssize_t read = Region::read(buffer);
- if (read < 0) return status_t(read);
-#if VALIDATE_REGIONS
- validate(*this, "read(Parcel)");
-#endif
- return NO_ERROR;
-}
-
ssize_t Region::write(void* buffer, size_t size) const
{
#if VALIDATE_REGIONS
@@ -570,12 +533,14 @@
#endif
const size_t count = mStorage.size();
const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
- if (sizeNeeded > size) return NO_MEMORY;
- int32_t* const p = static_cast<int32_t*>(buffer);
- *p = count;
- memcpy(p+1, &mBounds, sizeof(Rect));
- if (count) {
- memcpy(p+5, mStorage.array(), count*sizeof(Rect));
+ if (buffer != NULL) {
+ if (sizeNeeded > size) return NO_MEMORY;
+ int32_t* const p = static_cast<int32_t*>(buffer);
+ *p = count;
+ memcpy(p+1, &mBounds, sizeof(Rect));
+ if (count) {
+ memcpy(p+5, mStorage.array(), count*sizeof(Rect));
+ }
}
return ssize_t(sizeNeeded);
}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 8c24ee1..2c0399e 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -59,8 +59,10 @@
Location getLastKnownLocation(String provider);
- /* used by location providers to tell the location manager when it has a new location */
- void reportLocation(in Location location);
+ // Used by location providers to tell the location manager when it has a new location.
+ // Passive is true if the location is coming from the passive provider, in which case
+ // it need not be shared with other providers.
+ void reportLocation(in Location location, boolean passive);
String getFromLocation(double latitude, double longitude, int maxResults,
in GeocoderParams params, out List<Address> addrs);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 9027fc2..da760a1 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -81,6 +81,19 @@
public static final String GPS_PROVIDER = "gps";
/**
+ * A special location provider for receiving locations without actually initiating
+ * a location fix. This provider can be used to passively receive location updates
+ * when other applications or services request them without actually requesting
+ * the locations yourself. This provider will return locations generated by other
+ * providers. You can query the {@link Location#getProvider()} method to determine
+ * the origin of the location update.
+ *
+ * Requires the permission android.permission.ACCESS_FINE_LOCATION, although if the GPS
+ * is not enabled this provider might only return coarse fixes.
+ */
+ public static final String PASSIVE_PROVIDER = "passive";
+
+ /**
* Key used for the Bundle extra holding a boolean indicating whether
* a proximity alert is entering (true) or exiting (false)..
*/
diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java
index 3faba58..bb3e2a5 100644
--- a/location/java/android/location/LocationProvider.java
+++ b/location/java/android/location/LocationProvider.java
@@ -71,6 +71,10 @@
* false otherwise.
*/
public boolean meetsCriteria(Criteria criteria) {
+ // We do not want to match the special passive provider based on criteria.
+ if (LocationManager.PASSIVE_PROVIDER.equals(mName)) {
+ return false;
+ }
if ((criteria.getAccuracy() != Criteria.NO_REQUIREMENT) &&
(criteria.getAccuracy() < getAccuracy())) {
return false;
diff --git a/location/java/android/location/provider/LocationProvider.java b/location/java/android/location/provider/LocationProvider.java
index 0d028c0..4163def 100644
--- a/location/java/android/location/provider/LocationProvider.java
+++ b/location/java/android/location/provider/LocationProvider.java
@@ -156,7 +156,7 @@
*/
public void reportLocation(Location location) {
try {
- mLocationManager.reportLocation(location);
+ mLocationManager.reportLocation(location, false);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in reportLocation: ", e);
}
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index dce3b27..8e84106 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -863,7 +863,7 @@
}
try {
- mLocationManager.reportLocation(mLocation);
+ mLocationManager.reportLocation(mLocation, false);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling reportLocation");
}
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index 2f6fdee..bc1893e 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -143,7 +143,7 @@
mLocation.set(l);
mHasLocation = true;
try {
- mLocationManager.reportLocation(mLocation);
+ mLocationManager.reportLocation(mLocation, false);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling reportLocation");
}
diff --git a/location/java/com/android/internal/location/PassiveProvider.java b/location/java/com/android/internal/location/PassiveProvider.java
new file mode 100644
index 0000000..7eb711d
--- /dev/null
+++ b/location/java/com/android/internal/location/PassiveProvider.java
@@ -0,0 +1,139 @@
+/*
+ * 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.internal.location;
+
+import android.location.ILocationManager;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationProvider;
+import android.location.LocationProviderInterface;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A passive location provider reports locations received from other providers
+ * for clients that want to listen passively without actually triggering
+ * location updates.
+ *
+ * {@hide}
+ */
+public class PassiveProvider implements LocationProviderInterface {
+
+ private static final String TAG = "PassiveProvider";
+
+ private final ILocationManager mLocationManager;
+ private boolean mTracking;
+
+ public PassiveProvider(ILocationManager locationManager) {
+ mLocationManager = locationManager;
+ }
+
+ public String getName() {
+ return LocationManager.PASSIVE_PROVIDER;
+ }
+
+ public boolean requiresNetwork() {
+ return false;
+ }
+
+ public boolean requiresSatellite() {
+ return false;
+ }
+
+ public boolean requiresCell() {
+ return false;
+ }
+
+ public boolean hasMonetaryCost() {
+ return false;
+ }
+
+ public boolean supportsAltitude() {
+ return false;
+ }
+
+ public boolean supportsSpeed() {
+ return false;
+ }
+
+ public boolean supportsBearing() {
+ return false;
+ }
+
+ public int getPowerRequirement() {
+ return -1;
+ }
+
+ public int getAccuracy() {
+ return -1;
+ }
+
+ public boolean isEnabled() {
+ return true;
+ }
+
+ public void enable() {
+ }
+
+ public void disable() {
+ }
+
+ public int getStatus(Bundle extras) {
+ if (mTracking) {
+ return LocationProvider.AVAILABLE;
+ } else {
+ return LocationProvider.TEMPORARILY_UNAVAILABLE;
+ }
+ }
+
+ public long getStatusUpdateTime() {
+ return -1;
+ }
+
+ public void enableLocationTracking(boolean enable) {
+ mTracking = enable;
+ }
+
+ public void setMinTime(long minTime) {
+ }
+
+ public void updateNetworkState(int state, NetworkInfo info) {
+ }
+
+ public void updateLocation(Location location) {
+ if (mTracking) {
+ try {
+ // pass the location back to the location manager
+ mLocationManager.reportLocation(location, true);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException calling reportLocation");
+ }
+ }
+ }
+
+ public boolean sendExtraCommand(String command, Bundle extras) {
+ return false;
+ }
+
+ public void addListener(int uid) {
+ }
+
+ public void removeListener(int uid) {
+ }
+}
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 62a4fe9..18ce5c1 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -327,8 +327,6 @@
* iterates through all the active streams and pauses any that
* are playing. It also sets a flag so that any streams that
* are playing can be resumed by calling autoResume().
- *
- * @hide
*/
public native final void autoPause();
@@ -337,8 +335,6 @@
*
* Automatically resumes all streams that were paused in previous
* calls to autoPause().
- *
- * @hide
*/
public native final void autoResume();
@@ -412,8 +408,6 @@
/**
* Interface definition for a callback to be invoked when all the
* sounds are loaded.
- *
- * @hide
*/
public interface OnLoadCompleteListener
{
@@ -429,8 +423,6 @@
/**
* Sets the callback hook for the OnLoadCompleteListener.
- *
- * @hide
*/
public void setOnLoadCompleteListener(OnLoadCompleteListener listener)
{
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 1c9f4fd..59a5f9d 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -401,6 +401,9 @@
void AwesomePlayer::onBufferingUpdate() {
Mutex::Autolock autoLock(mLock);
+ if (!mBufferingEventPending) {
+ return;
+ }
mBufferingEventPending = false;
if (mDurationUs >= 0) {
@@ -425,6 +428,9 @@
// Posted whenever any stream finishes playing.
Mutex::Autolock autoLock(mLock);
+ if (!mStreamDoneEventPending) {
+ return;
+ }
mStreamDoneEventPending = false;
if (mFlags & LOOPING) {
@@ -918,6 +924,12 @@
void AwesomePlayer::onCheckAudioStatus() {
Mutex::Autolock autoLock(mLock);
+ if (!mAudioStatusEventPending) {
+ // Event was dispatched and while we were blocking on the mutex,
+ // has already been cancelled.
+ return;
+ }
+
mAudioStatusEventPending = false;
if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 75b7b6f..6cf7cff 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -102,7 +102,6 @@
{ MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
{ MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
{ MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
- { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
{ MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
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/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index d43039d..ea0fc65 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -66,6 +66,7 @@
import java.io.EOFException;
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
@@ -517,6 +518,9 @@
}
}
}
+ } catch (FileNotFoundException fnf) {
+ // Probably innocuous
+ Log.v(TAG, "No ancestral data");
} catch (IOException e) {
Log.w(TAG, "Unable to read token file", e);
}
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 d280475..b566fb7e 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,114 @@
// the status bar should be totally disabled, the calls below will
// have no effect until the device is unlocked.
if (mStatusBarManager != null) {
+ long ident = Binder.clearCallingIdentity();
mStatusBarManager.disable(enabled
? StatusBarManager.DISABLE_NOTIFICATION_TICKER
: StatusBarManager.DISABLE_NONE);
- }
- }
-
- private void setMode(int modeType, int modeNight) throws RemoteException {
- 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);
}
}
+ 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;
+ am.updateConfiguration(config);
+ }
+ 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/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index e12f2e1..9068966 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -71,6 +71,7 @@
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.location.LocationProviderProxy;
import com.android.internal.location.MockProvider;
+import com.android.internal.location.PassiveProvider;
/**
* The service class that manages LocationProviders and issues location
@@ -452,6 +453,11 @@
mGpsLocationProvider = gpsProvider;
}
+ // create a passive location provider, which is always enabled
+ PassiveProvider passiveProvider = new PassiveProvider(this);
+ addProvider(passiveProvider);
+ mEnabledProviders.add(passiveProvider.getName());
+
// initialize external network location and geocoder services
Resources resources = mContext.getResources();
String serviceName = resources.getString(
@@ -538,7 +544,8 @@
}
private void checkPermissionsSafe(String provider) {
- if (LocationManager.GPS_PROVIDER.equals(provider)
+ if ((LocationManager.GPS_PROVIDER.equals(provider)
+ || LocationManager.PASSIVE_PROVIDER.equals(provider))
&& (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)) {
throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
@@ -1343,7 +1350,7 @@
}
}
- public void reportLocation(Location location) {
+ public void reportLocation(Location location, boolean passive) {
if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
@@ -1351,6 +1358,7 @@
mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
+ m.arg1 = (passive ? 1 : 0);
mLocationHandler.sendMessageAtFrontOfQueue(m);
}
@@ -1415,8 +1423,8 @@
return true;
}
- private void handleLocationChangedLocked(Location location) {
- String provider = location.getProvider();
+ private void handleLocationChangedLocked(Location location, boolean passive) {
+ String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null || records.size() == 0) {
return;
@@ -1502,17 +1510,20 @@
synchronized (mLock) {
Location location = (Location) msg.obj;
String provider = location.getProvider();
+ boolean passive = (msg.arg1 == 1);
- // notify other providers of the new location
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- LocationProviderInterface p = mProviders.get(i);
- if (!provider.equals(p.getName())) {
- p.updateLocation(location);
+ if (!passive) {
+ // notify other providers of the new location
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ LocationProviderInterface p = mProviders.get(i);
+ if (!provider.equals(p.getName())) {
+ p.updateLocation(location);
+ }
}
}
if (isAllowedBySettingsLocked(provider)) {
- handleLocationChangedLocked(location);
+ handleLocationChangedLocked(location, passive);
}
}
}
@@ -1687,6 +1698,10 @@
boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
checkMockPermissionsSafe();
+ if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
+ throw new IllegalArgumentException("Cannot mock the passive location provider");
+ }
+
long identity = Binder.clearCallingIdentity();
synchronized (mLock) {
MockProvider provider = new MockProvider(name, this,
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index cf083c0..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/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 586f63f..6797f78 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1654,7 +1654,7 @@
if (DBG) log("processPlusCodeWithinNanp,networkDialStr=" + networkDialStr);
// If there is a plus sign at the beginning of the dial string,
// Convert the plus sign to the default IDP since it's an international number
- if (networkDialStr != null &
+ if (networkDialStr != null &&
networkDialStr.charAt(0) == PLUS_SIGN_CHAR &&
networkDialStr.length() > 1) {
String newStr = networkDialStr.substring(1);
diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java
index 3e7094e..71936f1 100644
--- a/telephony/java/com/android/internal/telephony/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/IccUtils.java
@@ -397,7 +397,7 @@
int bits = data[valueIndex++] & 0xFF;
int colorNumber = data[valueIndex++] & 0xFF;
int clutOffset = ((data[valueIndex++] & 0xFF) << 8)
- | data[valueIndex++];
+ | (data[valueIndex++] & 0xFF);
length = length - 6;
int[] colorIndexArray = getCLUT(data, clutOffset, colorNumber);
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");
-
}
-
-
-
+
}