Merge "Update status bar icons for BT reverse tethering." into honeycomb
diff --git a/api/11.xml b/api/11.xml
index 43bb440..e2f8025 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -61129,17 +61129,6 @@
visibility="public"
>
</method>
-<method name="getGL"
- return="javax.microedition.khronos.opengles.GL"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
<method name="getHeight"
return="int"
abstract="false"
diff --git a/api/current.xml b/api/current.xml
index 57a76de..8b0c555 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1255,17 +1255,6 @@
visibility="public"
>
</field>
-<field name="WRITE_MEDIA_STORAGE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.permission.WRITE_MEDIA_STORAGE""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="WRITE_SECURE_SETTINGS"
type="java.lang.String"
transient="false"
@@ -1486,7 +1475,7 @@
type="int"
transient="false"
volatile="false"
- value="17432591"
+ value="17432589"
static="true"
final="true"
deprecated="not deprecated"
@@ -1519,29 +1508,7 @@
type="int"
transient="false"
volatile="false"
- value="17432593"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="animator_fade_in"
- type="int"
- transient="false"
- volatile="false"
- value="17432589"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="animator_fade_out"
- type="int"
- transient="false"
- volatile="false"
- value="17432590"
+ value="17432591"
static="true"
final="true"
deprecated="not deprecated"
@@ -1596,7 +1563,7 @@
type="int"
transient="false"
volatile="false"
- value="17432592"
+ value="17432590"
static="true"
final="true"
deprecated="not deprecated"
@@ -1618,7 +1585,7 @@
type="int"
transient="false"
volatile="false"
- value="17432594"
+ value="17432592"
static="true"
final="true"
deprecated="not deprecated"
@@ -19996,6 +19963,42 @@
</parameter>
</method>
</class>
+<class name="ArgbEvaluator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.TypeEvaluator">
+</implements>
+<constructor name="ArgbEvaluator"
+ type="android.animation.ArgbEvaluator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
<class name="DoubleEvaluator"
extends="java.lang.Object"
abstract="false"
@@ -20962,42 +20965,6 @@
</parameter>
</method>
</class>
-<class name="RGBEvaluator"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.animation.TypeEvaluator">
-</implements>
-<constructor name="RGBEvaluator"
- type="android.animation.RGBEvaluator"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="evaluate"
- return="java.lang.Object"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="fraction" type="float">
-</parameter>
-<parameter name="startValue" type="java.lang.Object">
-</parameter>
-<parameter name="endValue" type="java.lang.Object">
-</parameter>
-</method>
-</class>
<interface name="TimeInterpolator"
abstract="true"
static="false"
@@ -58409,6 +58376,17 @@
visibility="public"
>
</method>
+<method name="isEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<field name="applicationInfo"
type="android.content.pm.ApplicationInfo"
transient="false"
@@ -78255,17 +78233,6 @@
visibility="public"
>
</method>
-<method name="getGL"
- return="javax.microedition.khronos.opengles.GL"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="protected"
->
-</method>
<method name="getHeight"
return="int"
abstract="false"
@@ -136934,6 +136901,19 @@
deprecated="not deprecated"
visibility="protected"
>
+<parameter name="result" type="Result">
+</parameter>
+</method>
+<method name="onCancelled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
</method>
<method name="onPostExecute"
return="void"
@@ -140826,6 +140806,17 @@
visibility="public"
>
</method>
+<method name="isExternalStorageEmulated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="isExternalStorageRemovable"
return="boolean"
abstract="false"
@@ -166353,8 +166344,6 @@
</parameter>
<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
</parameter>
-<parameter name="layout" type="android.renderscript.Allocation.CubemapLayout">
-</parameter>
<parameter name="usage" type="int">
</parameter>
</method>
@@ -166372,8 +166361,6 @@
</parameter>
<parameter name="b" type="android.graphics.Bitmap">
</parameter>
-<parameter name="layout" type="android.renderscript.Allocation.CubemapLayout">
-</parameter>
</method>
<method name="createFromBitmap"
return="android.renderscript.Allocation"
@@ -166633,39 +166620,6 @@
>
</field>
</class>
-<class name="Allocation.CubemapLayout"
- extends="java.lang.Enum"
- abstract="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="valueOf"
- return="android.renderscript.Allocation.CubemapLayout"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="name" type="java.lang.String">
-</parameter>
-</method>
-<method name="values"
- return="android.renderscript.Allocation.CubemapLayout[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-</class>
<class name="Allocation.MipmapControl"
extends="java.lang.Enum"
abstract="false"
@@ -198616,6 +198570,17 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
+<method name="isLenient"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="nextBoolean"
return="boolean"
abstract="false"
@@ -198746,21 +198711,6 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
-<method name="syntaxError"
- return="java.io.IOException"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="message" type="java.lang.String">
-</parameter>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
</class>
<class name="JsonToken"
extends="java.lang.Enum"
@@ -198893,6 +198843,17 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
+<method name="isLenient"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="name"
return="android.util.JsonWriter"
abstract="false"
@@ -198934,6 +198895,19 @@
<parameter name="indent" type="java.lang.String">
</parameter>
</method>
+<method name="setLenient"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lenient" type="boolean">
+</parameter>
+</method>
<method name="value"
return="android.util.JsonWriter"
abstract="false"
@@ -198994,6 +198968,21 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
+<method name="value"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Number">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
</class>
<class name="Log"
extends="java.lang.Object"
@@ -199373,6 +199362,25 @@
</parameter>
</method>
</class>
+<class name="MalformedJsonException"
+ extends="java.io.IOException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MalformedJsonException"
+ type="android.util.MalformedJsonException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
<class name="MonthDisplayHelper"
extends="java.lang.Object"
abstract="false"
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 6e589e4..bcab66e 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -215,7 +215,7 @@
(toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
// special case for colors: ignore valueType and get ints
getFloats = false;
- anim.setEvaluator(new RGBEvaluator());
+ anim.setEvaluator(new ArgbEvaluator());
}
if (getFloats) {
diff --git a/core/java/android/animation/RGBEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
similarity index 97%
rename from core/java/android/animation/RGBEvaluator.java
rename to core/java/android/animation/ArgbEvaluator.java
index bae0af0..c3875be 100644
--- a/core/java/android/animation/RGBEvaluator.java
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -20,7 +20,7 @@
* This evaluator can be used to perform type interpolation between integer
* values that represent ARGB colors.
*/
-public class RGBEvaluator implements TypeEvaluator {
+public class ArgbEvaluator implements TypeEvaluator {
/**
* This function returns the calculated in-between value for a color
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index cfecec1..f884473 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -862,7 +862,7 @@
* of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
* are not one of these primitive types, or if different evaluation is desired (such as is
* necessary with int values that represent colors), a custom evaluator needs to be assigned.
- * For example, when running an animation on color values, the {@link RGBEvaluator}
+ * For example, when running an animation on color values, the {@link ArgbEvaluator}
* should be used to get correct RGB color interpolation.
*
* <p>If this ValueAnimator has only one set of values being animated between, this evaluator
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 8b292c9..2fa2834 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -237,43 +237,7 @@
private BroadcastReceiver mConnectivityIntentReceiver =
new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
- NetworkInfo networkInfo =
- intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
- NetworkInfo.State state = (networkInfo == null ? NetworkInfo.State.UNKNOWN :
- networkInfo.getState());
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "received connectivity action. network info: " + networkInfo);
- }
-
- final boolean wasConnected = mDataConnectionIsConnected;
- // only pay attention to the CONNECTED and DISCONNECTED states.
- // if connected, we are connected.
- // if disconnected, we may not be connected. in some cases, we may be connected on
- // a different network.
- // e.g., if switching from GPRS to WiFi, we may receive the CONNECTED to WiFi and
- // DISCONNECTED for GPRS in any order. if we receive the CONNECTED first, and then
- // a DISCONNECTED, we want to make sure we set mDataConnectionIsConnected to true
- // since we still have a WiFi connection.
- switch (state) {
- case CONNECTED:
- mDataConnectionIsConnected = true;
- break;
- case DISCONNECTED:
- mDataConnectionIsConnected = !intent.getBooleanExtra(
- ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
- break;
- default:
- // ignore the rest of the states -- leave our boolean alone.
- }
- if (mDataConnectionIsConnected) {
- if (!wasConnected) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Reconnection detected: clearing all backoffs");
- }
- mSyncStorageEngine.clearAllBackoffs();
- }
- sendCheckAlarmsMessage();
- }
+ sendCheckAlarmsMessage();
}
};
@@ -1409,8 +1373,12 @@
public void handleMessage(Message msg) {
long earliestFuturePollTime = Long.MAX_VALUE;
long nextPendingSyncTime = Long.MAX_VALUE;
+ // Setting the value here instead of a method because we want the dumpsys logs
+ // to have the most recent value used.
try {
waitUntilReadyToRun();
+ NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo();
+ mDataConnectionIsConnected = (networkInfo != null) && networkInfo.isConnected();
mSyncManagerWakeLock.acquire();
// Always do this first so that we be sure that any periodic syncs that
// are ready to run have been converted into pending syncs. This allows the
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index f16c4ef..2812477 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -98,6 +98,13 @@
}
return name;
}
+
+ /**
+ * Return whether this component and its enclosing application are enabled.
+ */
+ public boolean isEnabled() {
+ return enabled && applicationInfo.enabled;
+ }
/**
* Return the icon resource identifier to use for this component. If
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 5e96928..c76cc6c 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -131,6 +131,10 @@
long retValue = native_1x1_long();
mDatabase.logTimeStat(mSql, timeStart);
return retValue;
+ } catch (SQLiteDoneException e) {
+ throw new SQLiteDoneException(
+ "expected 1 row from this query but query returned no data. check the query: " +
+ mSql);
} finally {
releaseAndUnlock();
}
@@ -150,6 +154,10 @@
String retValue = native_1x1_string();
mDatabase.logTimeStat(mSql, timeStart);
return retValue;
+ } catch (SQLiteDoneException e) {
+ throw new SQLiteDoneException(
+ "expected 1 row from this query but query returned no data. check the query: " +
+ mSql);
} finally {
releaseAndUnlock();
}
@@ -172,6 +180,10 @@
} catch (IOException ex) {
Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex);
return null;
+ } catch (SQLiteDoneException e) {
+ throw new SQLiteDoneException(
+ "expected 1 row from this query but query returned no data. check the query: " +
+ mSql);
} finally {
releaseAndUnlock();
}
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 46a29a9..9f7e31c 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -26,6 +26,7 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -115,11 +116,11 @@
* <h2>Cancelling a task</h2>
* <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking
* this method will cause subsequent calls to {@link #isCancelled()} to return true.
- * After invoking this method, {@link #onCancelled()}, instead of {@link #onPostExecute(Object)}
- * will be invoked after {@link #doInBackground(Object[])} returns. To ensure that
- * a task is cancelled as quickly as possible, you should always check the return
- * value of {@link #isCancelled()} periodically from {@link #doInBackground(Object[])},
- * if possible (inside a loop for instance.)</p>
+ * After invoking this method, {@link #onCancelled(Object)}, instead of
+ * {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])}
+ * returns. To ensure that a task is cancelled as quickly as possible, you should always
+ * check the return value of {@link #isCancelled()} periodically from
+ * {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p>
*
* <h2>Threading rules</h2>
* <p>There are a few threading rules that must be followed for this class to
@@ -173,6 +174,8 @@
private final FutureTask<Result> mFuture;
private volatile Status mStatus = Status.PENDING;
+
+ private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
/**
* Indicates the current status of the task. Each status will be set only once
@@ -204,15 +207,10 @@
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
+ mTaskInvoked.set(true);
+
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-
- Result result = doInBackground(mParams);
-
- Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
- new AsyncTaskResult<Result>(AsyncTask.this, result));
- message.sendToTarget();
-
- return result;
+ return postResult(doInBackground(mParams));
}
};
@@ -220,14 +218,16 @@
@Override
protected void done() {
try {
- get();
+ final Result result = get();
+
+ postResultIfNotInvoked(result);
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
- // Taken care of in the WorkerRunnable
+ postResultIfNotInvoked(null);
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
@@ -236,6 +236,20 @@
};
}
+ private void postResultIfNotInvoked(Result result) {
+ final boolean wasTaskInvoked = mTaskInvoked.get();
+ if (!wasTaskInvoked) {
+ postResult(result);
+ }
+ }
+
+ private Result postResult(Result result) {
+ Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
+ new AsyncTaskResult<Result>(this, result));
+ message.sendToTarget();
+ return result;
+ }
+
/**
* Returns the current status of this task.
*
@@ -282,7 +296,7 @@
*
* @see #onPreExecute
* @see #doInBackground
- * @see #onCancelled()
+ * @see #onCancelled(Object)
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onPostExecute(Result result) {
@@ -302,9 +316,33 @@
}
/**
- * Runs on the UI thread after {@link #cancel(boolean)} is invoked and
- * {@link #doInBackground(Object[])} has finished.
+ * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
+ * {@link #doInBackground(Object[])} has finished.</p>
+ *
+ * <p>The default implementation simply invokes {@link #onCancelled()} and
+ * ignores the result. If you write your own implementation, do not call
+ * <code>super.onCancelled(result)</code>.</p>
*
+ * @param result The result, if any, computed in
+ * {@link #doInBackground(Object[])}, can be null
+ *
+ * @see #cancel(boolean)
+ * @see #isCancelled()
+ */
+ @SuppressWarnings({"UnusedParameters"})
+ protected void onCancelled(Result result) {
+ onCancelled();
+ }
+
+ /**
+ * <p>Applications should preferably override {@link #onCancelled(Object)}.
+ * This method is invoked by the default implementation of
+ * {@link #onCancelled(Object)}.</p>
+ *
+ * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
+ * {@link #doInBackground(Object[])} has finished.</p>
+ *
+ * @see #onCancelled(Object)
* @see #cancel(boolean)
* @see #isCancelled()
*/
@@ -335,7 +373,7 @@
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.</p>
*
- * <p>Calling this method will result in {@link #onCancelled()} being
+ * <p>Calling this method will result in {@link #onCancelled(Object)} being
* invoked on the UI thread after {@link #doInBackground(Object[])}
* returns. Calling this method guarantees that {@link #onPostExecute(Object)}
* is never invoked. After invoking this method, you should check the
@@ -352,7 +390,7 @@
* <tt>true</tt> otherwise
*
* @see #isCancelled()
- * @see #onCancelled()
+ * @see #onCancelled(Object)
*/
public final boolean cancel(boolean mayInterruptIfRunning) {
return mFuture.cancel(mayInterruptIfRunning);
@@ -452,7 +490,7 @@
private void finish(Result result) {
if (isCancelled()) {
- onCancelled();
+ onCancelled(result);
} else {
onPostExecute(result);
}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 4688847..4f188f8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -414,8 +414,6 @@
* emulated. If true, the device does not have real external storage
* and certain system services such as the package manager use this
* to determine where to install an application.
- *
- * @hide
*/
public static boolean isExternalStorageEmulated() {
if (mIsExternalStorageEmulated == null) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d1ca0c9..ee091f0 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3430,12 +3430,6 @@
* <th colspan='4'>PhoneLookup</th>
* </tr>
* <tr>
- * <td>long</td>
- * <td>{@link #_ID}</td>
- * <td>read-only</td>
- * <td>Data row ID.</td>
- * </tr>
- * <tr>
* <td>String</td>
* <td>{@link #NUMBER}</td>
* <td>read-only</td>
@@ -3462,6 +3456,12 @@
* <th colspan='4'>Join with {@link Contacts}</th>
* </tr>
* <tr>
+ * <td>long</td>
+ * <td>{@link #_ID}</td>
+ * <td>read-only</td>
+ * <td>Contact ID.</td>
+ * </tr>
+ * <tr>
* <td>String</td>
* <td>{@link #LOOKUP_KEY}</td>
* <td>read-only</td>
diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java
index 8025545..8f44895 100644
--- a/core/java/android/util/JsonReader.java
+++ b/core/java/android/util/JsonReader.java
@@ -16,6 +16,7 @@
package android.util;
+import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.io.Closeable;
@@ -249,6 +250,13 @@
}
/**
+ * Returns true if this parser is liberal in what it accepts.
+ */
+ public boolean isLenient() {
+ return lenient;
+ }
+
+ /**
* Consumes the next token from the JSON stream and asserts that it is the
* beginning of a new array.
*/
@@ -311,7 +319,7 @@
case EMPTY_DOCUMENT:
replaceTop(JsonScope.NONEMPTY_DOCUMENT);
JsonToken firstToken = nextValue();
- if (token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) {
+ if (!lenient && token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) {
throw new IOException(
"Expected JSON document to start with '[' or '{' but was " + token);
}
@@ -327,7 +335,15 @@
case NONEMPTY_OBJECT:
return nextInObject(false);
case NONEMPTY_DOCUMENT:
- return token = JsonToken.END_DOCUMENT;
+ try {
+ JsonToken token = nextValue();
+ if (lenient) {
+ return token;
+ }
+ throw syntaxError("Expected EOF");
+ } catch (EOFException e) {
+ return token = JsonToken.END_DOCUMENT; // TODO: avoid throwing here?
+ }
case CLOSED:
throw new IllegalStateException("JsonReader is closed");
default:
@@ -758,7 +774,7 @@
}
}
- throw syntaxError("End of input");
+ throw new EOFException("End of input");
}
private void checkLenient() throws IOException {
@@ -1030,8 +1046,6 @@
* form -12.34e+56. Fractional and exponential parts are optional. Leading
* zeroes are not allowed in the value or exponential part, but are allowed
* in the fraction.
- *
- * <p>This has a side effect of setting isInteger.
*/
private JsonToken decodeNumber(char[] chars, int offset, int length) {
int i = offset;
@@ -1085,8 +1099,8 @@
* Throws a new IO exception with the given message and a context snippet
* with this reader's content.
*/
- public IOException syntaxError(String message) throws IOException {
- throw new JsonSyntaxException(message + " near " + getSnippet());
+ private IOException syntaxError(String message) throws IOException {
+ throw new MalformedJsonException(message + " near " + getSnippet());
}
private CharSequence getSnippet() {
@@ -1097,10 +1111,4 @@
snippet.append(buffer, pos, afterPos);
return snippet;
}
-
- private static class JsonSyntaxException extends IOException {
- private JsonSyntaxException(String s) {
- super(s);
- }
- }
}
diff --git a/core/java/android/util/JsonWriter.java b/core/java/android/util/JsonWriter.java
index 89cad79..47e84c5 100644
--- a/core/java/android/util/JsonWriter.java
+++ b/core/java/android/util/JsonWriter.java
@@ -138,6 +138,8 @@
*/
private String separator = ":";
+ private boolean lenient;
+
/**
* Creates a new instance that writes a JSON-encoded stream to {@code out}.
* For best performance, ensure {@link Writer} is buffered; wrapping in
@@ -169,6 +171,29 @@
}
/**
+ * Configure this writer to relax its syntax rules. By default, this writer
+ * only emits well-formed JSON as specified by <a
+ * href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. Setting the writer
+ * to lenient permits the following:
+ * <ul>
+ * <li>Top-level values of any type. With strict writing, the top-level
+ * value must be an object or an array.
+ * <li>Numbers may be {@link Double#isNaN() NaNs} or {@link
+ * Double#isInfinite() infinities}.
+ * </ul>
+ */
+ public void setLenient(boolean lenient) {
+ this.lenient = lenient;
+ }
+
+ /**
+ * Returns true if this writer has relaxed syntax rules.
+ */
+ public boolean isLenient() {
+ return lenient;
+ }
+
+ /**
* Begins encoding a new array. Each call to this method must be paired with
* a call to {@link #endArray}.
*
@@ -306,11 +331,11 @@
* Encodes {@code value}.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
- * {@link Double#isInfinite() infinities}.
+ * {@link Double#isInfinite() infinities} unless this writer is lenient.
* @return this writer.
*/
public JsonWriter value(double value) throws IOException {
- if (Double.isNaN(value) || Double.isInfinite(value)) {
+ if (!lenient && (Double.isNaN(value) || Double.isInfinite(value))) {
throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
}
beforeValue(false);
@@ -330,6 +355,28 @@
}
/**
+ * Encodes {@code value}.
+ *
+ * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
+ * {@link Double#isInfinite() infinities} unless this writer is lenient.
+ * @return this writer.
+ */
+ public JsonWriter value(Number value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+
+ String string = value.toString();
+ if (!lenient &&
+ (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN"))) {
+ throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
+ }
+ beforeValue(false);
+ out.append(string);
+ return this;
+ }
+
+ /**
* Ensures all buffered data is written to the underlying {@link Writer}
* and flushes that writer.
*/
@@ -364,7 +411,6 @@
switch (c) {
case '"':
case '\\':
- case '/':
out.write('\\');
out.write(c);
break;
@@ -439,7 +485,7 @@
private void beforeValue(boolean root) throws IOException {
switch (peek()) {
case EMPTY_DOCUMENT: // first in document
- if (!root) {
+ if (!lenient && !root) {
throw new IllegalStateException(
"JSON must start with an array or an object.");
}
diff --git a/core/java/android/util/MalformedJsonException.java b/core/java/android/util/MalformedJsonException.java
new file mode 100644
index 0000000..63c19ff
--- /dev/null
+++ b/core/java/android/util/MalformedJsonException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 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.util;
+
+import java.io.IOException;
+
+/**
+ * Thrown when a reader encounters malformed JSON. Some syntax errors can be
+ * ignored by calling {@link JsonReader#setLenient(boolean)}.
+ */
+public final class MalformedJsonException extends IOException {
+ private static final long serialVersionUID = 1L;
+
+ public MalformedJsonException(String message) {
+ super(message);
+ }
+}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 366393c..7c55f7b 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1073,11 +1073,6 @@
}
}
surfaceChanged = true;
-
- if (mAttachInfo.mHardwareRenderer != null) {
- // This will bail out early if already initialized
- mAttachInfo.mHardwareRenderer.initialize(mHolder);
- }
}
if (surfaceChanged) {
mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 700d313..a322fa3d 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -34,7 +34,7 @@
import android.view.inputmethod.InputMethodManager;
class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
- View.OnLongClickListener {
+ View.OnLongClickListener, View.OnClickListener {
private View mCustomView;
private EditText mEditText;
private TextView mMatches;
@@ -53,6 +53,7 @@
// Override long click so that select ActionMode is not opened, which
// would exit find ActionMode.
mEditText.setOnLongClickListener(this);
+ mEditText.setOnClickListener(this);
setText("");
mMatches = (TextView) mCustomView.findViewById(
com.android.internal.R.id.matches);
@@ -105,7 +106,17 @@
throw new AssertionError(
"No WebView for FindActionModeCallback::findNext");
}
+ if (!mMatchesFound) {
+ findAll();
+ return;
+ }
+ if (0 == mNumberOfMatches) {
+ // There are no matches, so moving to the next match will not do
+ // anything.
+ return;
+ }
mWebView.findNext(next);
+ updateMatchesString();
}
/*
@@ -158,6 +169,13 @@
@Override
public boolean onLongClick(View v) { return true; }
+ // OnClickListener implementation
+
+ @Override
+ public void onClick(View v) {
+ findNext(true);
+ }
+
// ActionMode.Callback implementation
@Override
@@ -193,15 +211,6 @@
"No WebView for FindActionModeCallback::onActionItemClicked");
}
mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
- if (!mMatchesFound) {
- findAll();
- return true;
- }
- if (0 == mNumberOfMatches) {
- // There are no matches, so moving to the next match will not do
- // anything.
- return true;
- }
switch(item.getItemId()) {
case com.android.internal.R.id.find_prev:
findNext(false);
@@ -212,7 +221,6 @@
default:
return false;
}
- updateMatchesString();
return true;
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 4c2f0b4..1313fcc 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -204,11 +204,6 @@
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
- if (!mWebView.nativeCursorMatchesFocus()) {
- return down ? mWebView.onKeyDown(keyCode, event) : mWebView
- .onKeyUp(keyCode, event);
-
- }
isArrowKey = true;
break;
}
@@ -258,10 +253,6 @@
if (isPopupShowing()) {
return super.dispatchKeyEvent(event);
}
- if (!mWebView.nativeCursorMatchesFocus()) {
- return down ? mWebView.onKeyDown(keyCode, event) : mWebView
- .onKeyUp(keyCode, event);
- }
// Center key should be passed to a potential onClick
if (!down) {
mWebView.centerKeyPressOnTextField();
@@ -753,12 +744,7 @@
if (event.getAction() != MotionEvent.ACTION_MOVE) {
return false;
}
- // If the Cursor is not on the text input, webview should handle the
- // trackball
- if (!mWebView.nativeCursorMatchesFocus()) {
- return mWebView.onTrackballEvent(event);
- }
- Spannable text = (Spannable) getText();
+ Spannable text = getText();
MovementMethod move = getMovementMethod();
if (move != null && getLayout() != null &&
move.onTrackballEvent(this, text, event)) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 61f0bce..4a9e441 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -56,6 +56,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemClock;
import android.provider.Settings;
import android.speech.tts.TextToSpeech;
import android.text.Selection;
@@ -2617,10 +2618,6 @@
private int computeRealHorizontalScrollRange() {
if (mDrawHistory) {
return mHistoryWidth;
- } else if (mHorizontalScrollBarMode == SCROLLBAR_ALWAYSOFF
- && !mZoomManager.canZoomOut()) {
- // only honor the scrollbar mode when it is at minimum zoom level
- return computeHorizontalScrollExtent();
} else {
// to avoid rounding error caused unnecessary scrollbar, use floor
return (int) Math.floor(mContentWidth * mZoomManager.getScale());
@@ -2651,10 +2648,6 @@
private int computeRealVerticalScrollRange() {
if (mDrawHistory) {
return mHistoryHeight;
- } else if (mVerticalScrollBarMode == SCROLLBAR_ALWAYSOFF
- && !mZoomManager.canZoomOut()) {
- // only honor the scrollbar mode when it is at minimum zoom level
- return computeVerticalScrollExtent();
} else {
// to avoid rounding error caused unnecessary scrollbar, use floor
return (int) Math.floor(mContentHeight * mZoomManager.getScale());
@@ -2961,12 +2954,12 @@
* @return boolean True if the find dialog is shown, false otherwise.
*/
public boolean showFindDialog(String text, boolean showIme) {
- mFindCallback = new FindActionModeCallback(mContext);
- if (startActionMode(mFindCallback) == null) {
+ FindActionModeCallback callback = new FindActionModeCallback(mContext);
+ if (startActionMode(callback) == null) {
// Could not start the action mode, so end Find on page
- mFindCallback = null;
return false;
}
+ mFindCallback = callback;
setFindIsUp(true);
mFindCallback.setWebView(this);
if (showIme) {
@@ -4564,14 +4557,6 @@
return true;
}
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
- || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- if (!nativePageShouldHandleShiftAndArrows() && !nativeCursorWantsKeyEvents()
- && !mSelectingText) {
- setUpSelect();
- }
- }
-
if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
if (event.hasNoModifiers()) {
pageUp(false);
@@ -4662,12 +4647,6 @@
if (!wantsKeyEvents) return false;
}
- if (keyCode != KeyEvent.KEYCODE_SHIFT_LEFT
- && keyCode != KeyEvent.KEYCODE_SHIFT_RIGHT) {
- // turn off copy select if a shift-key combo is pressed
- selectionDone();
- }
-
if (getSettings().getNavDump()) {
switch (keyCode) {
case KeyEvent.KEYCODE_4:
@@ -4766,14 +4745,6 @@
return true;
}
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
- || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- if (!nativePageShouldHandleShiftAndArrows() && copySelection()) {
- selectionDone();
- return true;
- }
- }
-
if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
&& keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
if (nativePageShouldHandleShiftAndArrows()) {
@@ -5234,7 +5205,8 @@
// Textfields, plugins, and contentEditable nodes need to receive the
// shift up key even if another key was released while the shift key
// was held down.
- if (!inEditingMode() && (mNativeClass == 0
+ boolean inEditingMode = inEditingMode();
+ if (!inEditingMode && (mNativeClass == 0
|| !nativePageShouldHandleShiftAndArrows())) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
mGotKeyDown = true;
@@ -5251,7 +5223,13 @@
}
if (dispatch) {
- return super.dispatchKeyEvent(event);
+ if (inEditingMode) {
+ // Ensure that the WebTextView gets the event, even if it does
+ // not currently have a bounds.
+ return mWebTextView.dispatchKeyEvent(event);
+ } else {
+ return super.dispatchKeyEvent(event);
+ }
} else {
// We didn't dispatch, so let something else handle the key
return false;
@@ -5344,17 +5322,10 @@
+ " numPointers=" + ev.getPointerCount());
}
- int action = ev.getAction();
- float x = ev.getX();
- float y = ev.getY();
- long eventTime = ev.getEventTime();
-
- // mDeferMultitouch is a hack for layout tests, where it is used to
- // force passing multi-touch events to webkit.
- // FIXME: always pass multi-touch events to webkit and remove everything
- // related to mDeferMultitouch.
- if (ev.getPointerCount() > 1 &&
- (mDeferMultitouch || mZoomManager.isZoomScaleFixed())) {
+ // Always pass multi-touch event to WebKit first.
+ // If WebKit doesn't consume it and set preventDefault to true,
+ // WebView's private handler will handle it.
+ if (ev.getPointerCount() > 1) {
if (DebugFlags.WEB_VIEW) {
Log.v(LOGTAG, "passing " + ev.getPointerCount() + " points to webkit");
}
@@ -5362,59 +5333,15 @@
return true;
}
- final ScaleGestureDetector detector =
- mZoomManager.getMultiTouchGestureDetector();
+ return handleTouchEventCommon(ev);
+ }
- if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1) {
- if (!detector.isInProgress() &&
- ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
- // Insert a fake pointer down event in order to start
- // the zoom scale detector.
- MotionEvent temp = MotionEvent.obtain(ev);
- // Clear the original event and set it to
- // ACTION_POINTER_DOWN.
- try {
- temp.setAction(temp.getAction() &
- ~MotionEvent.ACTION_MASK |
- MotionEvent.ACTION_POINTER_DOWN);
- detector.onTouchEvent(temp);
- } finally {
- temp.recycle();
- }
- }
+ private boolean handleTouchEventCommon(MotionEvent ev) {
+ int action = ev.getAction();
+ float x = ev.getX();
+ float y = ev.getY();
+ long eventTime = ev.getEventTime();
- detector.onTouchEvent(ev);
-
- if (detector.isInProgress()) {
- mLastTouchTime = eventTime;
- cancelLongPress();
- mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- if (!mZoomManager.supportsPanDuringZoom()) {
- return true;
- }
- mTouchMode = TOUCH_DRAG_MODE;
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- }
-
- x = detector.getFocusX();
- y = detector.getFocusY();
- action = ev.getAction() & MotionEvent.ACTION_MASK;
- if (action == MotionEvent.ACTION_POINTER_DOWN) {
- cancelTouch();
- action = MotionEvent.ACTION_DOWN;
- } else if (action == MotionEvent.ACTION_POINTER_UP) {
- // set mLastTouchX/Y to the remaining point
- mLastTouchX = x;
- mLastTouchY = y;
- } else if (action == MotionEvent.ACTION_MOVE) {
- // negative x or y indicate it is on the edge, skip it.
- if (x < 0 || y < 0) {
- return true;
- }
- }
- }
// Due to the touch screen edge effect, a touch closer to the edge
// always snapped to the edge. As getViewWidth() can be different from
@@ -5627,22 +5554,6 @@
break;
}
- // Only lock dragging to one axis if we don't have a scale in progress.
- // Scaling implies free-roaming movement. Note this is only ever a question
- // if mZoomManager.supportsPanDuringZoom() is true.
- if (detector != null && !detector.isInProgress()) {
- // if it starts nearly horizontal or vertical, enforce it
- int ax = Math.abs(deltaX);
- int ay = Math.abs(deltaY);
- if (ax > MAX_SLOPE_FOR_DIAG * ay) {
- mSnapScrollMode = SNAP_X;
- mSnapPositive = deltaX > 0;
- } else if (ay > MAX_SLOPE_FOR_DIAG * ax) {
- mSnapScrollMode = SNAP_Y;
- mSnapPositive = deltaY > 0;
- }
- }
-
mTouchMode = TOUCH_DRAG_MODE;
mLastTouchX = x;
mLastTouchY = y;
@@ -5899,13 +5810,82 @@
ted.mPoints[c] = new Point(x, y);
}
ted.mMetaState = ev.getMetaState();
- ted.mReprocess = mDeferTouchProcess;
+ ted.mReprocess = true;
+ ted.mMotionEvent = MotionEvent.obtain(ev);
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
cancelLongPress();
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
mPreventDefault = PREVENT_DEFAULT_IGNORE;
}
+ private boolean handleMultiTouchInWebView(MotionEvent ev) {
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime()
+ + " mTouchMode=" + mTouchMode
+ + " numPointers=" + ev.getPointerCount()
+ + " scrolloffset=(" + mScrollX + "," + mScrollY + ")");
+ }
+
+ final ScaleGestureDetector detector =
+ mZoomManager.getMultiTouchGestureDetector();
+ int action = ev.getAction();
+ float x = ev.getX();
+ float y = ev.getY();
+ long eventTime = ev.getEventTime();
+
+ if (!detector.isInProgress() &&
+ ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
+ // Insert a fake pointer down event in order to start
+ // the zoom scale detector.
+ MotionEvent temp = MotionEvent.obtain(ev);
+ // Clear the original event and set it to
+ // ACTION_POINTER_DOWN.
+ try {
+ temp.setAction(temp.getAction() &
+ ~MotionEvent.ACTION_MASK |
+ MotionEvent.ACTION_POINTER_DOWN);
+ detector.onTouchEvent(temp);
+ } finally {
+ temp.recycle();
+ }
+ }
+
+ detector.onTouchEvent(ev);
+
+ if (detector.isInProgress()) {
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "detector is in progress");
+ }
+ mLastTouchTime = eventTime;
+ cancelLongPress();
+ mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+ if (!mZoomManager.supportsPanDuringZoom()) {
+ return false;
+ }
+ mTouchMode = TOUCH_DRAG_MODE;
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ }
+
+ action = ev.getAction() & MotionEvent.ACTION_MASK;
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ cancelTouch();
+ action = MotionEvent.ACTION_DOWN;
+ } else if (action == MotionEvent.ACTION_POINTER_UP) {
+ // set mLastTouchX/Y to the remaining point
+ mLastTouchX = x;
+ mLastTouchY = y;
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ // negative x or y indicate it is on the edge, skip it.
+ if (x < 0 || y < 0) {
+ return false;
+ }
+ }
+
+ return handleTouchEventCommon(ev);
+ }
+
private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) {
if (shouldForwardTouchEvent()) {
if (removeEvents) {
@@ -7278,6 +7258,13 @@
// prevent default is not called in WebCore, so the
// message needs to be reprocessed in UI
TouchEventData ted = (TouchEventData) msg.obj;
+
+ if (ted.mPoints.length > 1) { // for multi-touch.
+ handleMultiTouchInWebView(ted.mMotionEvent);
+ break;
+ }
+
+ // Following is for single touch.
switch (ted.mAction) {
case MotionEvent.ACTION_DOWN:
mLastDeferTouchX = contentToViewX(ted.mPoints[0].x)
@@ -8103,7 +8090,6 @@
private native int nativeCursorFramePointer();
private native Rect nativeCursorNodeBounds();
private native int nativeCursorNodePointer();
- /* package */ native boolean nativeCursorMatchesFocus();
private native boolean nativeCursorIntersects(Rect visibleRect);
private native boolean nativeCursorIsAnchor();
private native boolean nativeCursorIsTextInput();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index a482b74..8d5e71a 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -33,6 +33,7 @@
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.KeyEvent;
+import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.webkit.DeviceMotionService;
@@ -114,8 +115,8 @@
*/
private int mViewportDensityDpi = -1;
- private int mRestoredScale = 0;
- private int mRestoredTextWrapScale = 0;
+ private float mRestoredScale = 0;
+ private float mRestoredTextWrapScale = 0;
private int mRestoredX = 0;
private int mRestoredY = 0;
@@ -830,6 +831,7 @@
Point[] mPoints;
int mMetaState;
boolean mReprocess;
+ MotionEvent mMotionEvent;
}
static class GeolocationPermissionsData {
@@ -2243,8 +2245,8 @@
}
// reset the scroll position, the restored offset and scales
- mWebkitScrollX = mWebkitScrollY = mRestoredX = mRestoredY
- = mRestoredScale = mRestoredTextWrapScale = 0;
+ mWebkitScrollX = mWebkitScrollY = mRestoredX = mRestoredY = 0;
+ mRestoredScale = mRestoredTextWrapScale = 0;
}
// called by JNI
@@ -2350,9 +2352,9 @@
mInitialViewState.mMobileSite = (0 == mViewportWidth);
if (mRestoredScale > 0) {
mInitialViewState.mIsRestored = true;
- mInitialViewState.mViewScale = mRestoredScale / 100.0f;
+ mInitialViewState.mViewScale = mRestoredScale;
if (mRestoredTextWrapScale > 0) {
- mInitialViewState.mTextWrapScale = mRestoredTextWrapScale / 100.0f;
+ mInitialViewState.mTextWrapScale = mRestoredTextWrapScale;
} else {
mInitialViewState.mTextWrapScale = mInitialViewState.mViewScale;
}
@@ -2409,7 +2411,7 @@
// know the exact scale. If mRestoredScale is non-zero, use it;
// otherwise just use mTextWrapScale as the initial scale.
data.mScale = mInitialViewState.mViewScale == 0
- ? (mRestoredScale > 0 ? mRestoredScale / 100.0f
+ ? (mRestoredScale > 0 ? mRestoredScale
: mInitialViewState.mTextWrapScale)
: mInitialViewState.mViewScale;
if (DebugFlags.WEB_VIEW_CORE) {
@@ -2442,7 +2444,7 @@
}
// called by JNI
- private void restoreScale(int scale, int textWrapScale) {
+ private void restoreScale(float scale, float textWrapScale) {
if (mBrowserFrame.firstLayoutDone() == false) {
mRestoredScale = scale;
if (mSettings.getUseWideViewPort()) {
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 7b9def0..e1392ae 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -223,6 +223,7 @@
null);
}
}
+ mDatabase.enableWriteAheadLogging();
// mDatabase should not be null,
// the only case is RequestAPI test has problem to create db
@@ -233,7 +234,7 @@
}
if (mDatabase.getVersion() != DATABASE_VERSION) {
- mDatabase.beginTransaction();
+ mDatabase.beginTransactionNonExclusive();
try {
upgradeDatabase();
mDatabase.setTransactionSuccessful();
@@ -261,6 +262,7 @@
CACHE_DATABASE_FILE, 0, null);
}
}
+ mCacheDatabase.enableWriteAheadLogging();
// mCacheDatabase should not be null,
// the only case is RequestAPI test has problem to create db
@@ -271,7 +273,7 @@
}
if (mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) {
- mCacheDatabase.beginTransaction();
+ mCacheDatabase.beginTransactionNonExclusive();
try {
upgradeCacheDatabase();
bootstrapCacheDatabase();
@@ -648,7 +650,7 @@
+ "WebViewWorkerThread instead of from "
+ Thread.currentThread().getName());
}
- mCacheDatabase.beginTransaction();
+ mCacheDatabase.beginTransactionNonExclusive();
return true;
}
return false;
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 2fd5bb1..b4a33de 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -150,6 +150,12 @@
private static float MINIMUM_SCALE_INCREMENT = 0.01f;
/*
+ * The touch points could be changed even the fingers stop moving.
+ * We use the following to filter out the zooming jitters.
+ */
+ private static float MINIMUM_SCALE_WITHOUT_JITTER = 0.05f;
+
+ /*
* The following member variables are only to be used for animating zoom. If
* mZoomScale is non-zero then we are in the middle of a zoom animation. The
* other variables are used as a cache (e.g. inverse) or as a way to store
@@ -684,6 +690,10 @@
} else {
scale = Math.max(scale, mActualScale * 0.8f);
}
+ // if the scale change is too small, regard it as jitter and skip it.
+ if (Math.abs(scale - mActualScale) < MINIMUM_SCALE_WITHOUT_JITTER) {
+ return false;
+ }
setZoomCenter(detector.getFocusX(), detector.getFocusY());
setZoomScale(scale, false);
mWebView.invalidate();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index b85670c..bccde8d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4810,7 +4810,10 @@
if (mFiltered && mPopup != null && mPopup.isShowing()) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
- getKeyDispatcherState().startTracking(event, this);
+ KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null) {
+ state.startTracking(event, this);
+ }
handled = true;
} else if (event.getAction() == KeyEvent.ACTION_UP
&& event.isTracking() && !event.isCanceled()) {
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index ee037cd..4d8d21f 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -607,10 +607,16 @@
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
- getKeyDispatcherState().startTracking(event, this);
+ KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null) {
+ state.startTracking(event, this);
+ }
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
- getKeyDispatcherState().handleUpEvent(event);
+ KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null) {
+ state.handleUpEvent(event);
+ }
if (event.isTracking() && !event.isCanceled()) {
dismissDropDown();
return true;
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 3bba816..444a163d 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -915,10 +915,16 @@
// to the drop down list but instead, consume it immediately
final View anchorView = mDropDownAnchorView;
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
- anchorView.getKeyDispatcherState().startTracking(event, this);
+ KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
+ if (state != null) {
+ state.startTracking(event, this);
+ }
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
- anchorView.getKeyDispatcherState().handleUpEvent(event);
+ KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
+ if (state != null) {
+ state.handleUpEvent(event);
+ }
if (event.isTracking() && !event.isCanceled()) {
dismiss();
return true;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 5a5b6f4..79d6a81 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1468,12 +1468,17 @@
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
- getKeyDispatcherState().startTracking(event, this);
+ KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null) {
+ state.startTracking(event, this);
+ }
return true;
- } else if (event.getAction() == KeyEvent.ACTION_UP
- && getKeyDispatcherState().isTracking(event) && !event.isCanceled()) {
- dismiss();
- return true;
+ } else if (event.getAction() == KeyEvent.ACTION_UP) {
+ KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null && state.isTracking(event) && !event.isCanceled()) {
+ dismiss();
+ return true;
+ }
}
return super.dispatchKeyEvent(event);
} else {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cc5be00..a1c286f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4672,6 +4672,9 @@
// don't let it be inserted into the text.
if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
|| shouldAdvanceFocusOnEnter()) {
+ if (mOnClickListener != null) {
+ return 0;
+ }
return -1;
}
}
@@ -4780,7 +4783,6 @@
}
hideControllers();
- stopSelectionActionMode();
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
@@ -5119,6 +5121,7 @@
if (mInputMethodState != null) {
mInputMethodState.mExtracting = req;
}
+ // This stops a possible text selection mode. Maybe not intended.
hideControllers();
}
@@ -6781,7 +6784,7 @@
sendOnTextChanged(buffer, start, before, after);
onTextChanged(buffer, start, before, after);
- // Hide the controller if the amount of content changed
+ // Hide the controllers if the amount of content changed
if (before != after) {
hideControllers();
}
@@ -8207,9 +8210,12 @@
selectCurrentWord();
}
- final InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(this, 0, null);
+ if (!mTextIsSelectable) {
+ // Show the IME, except when selection non editable text.
+ final InputMethodManager imm = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(this, 0, null);
+ }
ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
mSelectionActionMode = startActionMode(actionModeCallback);
@@ -8233,6 +8239,7 @@
private void stopSelectionActionMode() {
if (mSelectionActionMode != null) {
+ // This will hide the mSelectionModifierCursorController
mSelectionActionMode.finish();
}
}
@@ -8356,8 +8363,12 @@
if (mCustomSelectionActionModeCallback != null) {
mCustomSelectionActionModeCallback.onDestroyActionMode(mode);
}
- Selection.setSelection((Spannable) mText, getSelectionStart());
- hideSelectionModifierCursorController();
+ Selection.setSelection((Spannable) mText, getSelectionEnd());
+
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.hide();
+ }
+
mSelectionActionMode = null;
}
}
@@ -9173,16 +9184,12 @@
}
}
- private void hideSelectionModifierCursorController() {
- // No need to create the controller to hide it.
- if (mSelectionModifierCursorController != null) {
- mSelectionModifierCursorController.hide();
- }
- }
-
+ /**
+ * Hides the insertion controller and stops text selection mode, hiding the selection controller
+ */
private void hideControllers() {
hideInsertionPointCursorController();
- hideSelectionModifierCursorController();
+ stopSelectionActionMode();
}
/**
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 9381675..463902f 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -139,6 +139,10 @@
mReserveOverflow = reserveOverflow;
}
+ public View getOverflowButton() {
+ return mOverflowButton;
+ }
+
@Override
protected LayoutParams generateDefaultLayoutParams() {
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index fe41f52..b93fac4 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -68,6 +68,10 @@
}
}
+ public void setAnchorView(View anchor) {
+ mAnchorView = new WeakReference<View>(anchor);
+ }
+
public void show() {
if (!tryShow()) {
throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index ada4dd3..52e8f42 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -45,14 +45,10 @@
static jint com_android_internal_os_ZygoteInit_setreuid(
JNIEnv* env, jobject clazz, jint ruid, jint euid)
{
- int err;
-
- errno = 0;
- err = setreuid(ruid, euid);
-
- //LOGI("setreuid(%d,%d) err %d errno %d", ruid, euid, err, errno);
-
- return errno;
+ if (setreuid(ruid, euid) < 0) {
+ return errno;
+ }
+ return 0;
}
/*
@@ -62,14 +58,10 @@
static jint com_android_internal_os_ZygoteInit_setregid(
JNIEnv* env, jobject clazz, jint rgid, jint egid)
{
- int err;
-
- errno = 0;
- err = setregid(rgid, egid);
-
- //LOGI("setregid(%d,%d) err %d errno %d", rgid, egid, err, errno);
-
- return errno;
+ if (setregid(rgid, egid) < 0) {
+ return errno;
+ }
+ return 0;
}
/*
@@ -79,13 +71,10 @@
static jint com_android_internal_os_ZygoteInit_setpgid(
JNIEnv* env, jobject clazz, jint pid, jint pgid)
{
- int err;
-
- errno = 0;
-
- err = setpgid(pid, pgid);
-
- return errno;
+ if (setpgid(pid, pgid) < 0) {
+ return errno;
+ }
+ return 0;
}
/*
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1d43442..67adc28 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -540,7 +540,8 @@
android:description="@string/permdesc_sdcardWrite"
android:protectionLevel="dangerous" />
- <!-- Allows an application to write to internal media storage -->
+ <!-- Allows an application to write to internal media storage
+ @hide -->
<permission android:name="android.permission.WRITE_MEDIA_STORAGE"
android:permissionGroup="android.permission-group.STORAGE"
android:label="@string/permlab_mediaStorageWrite"
diff --git a/core/res/res/anim/animator_fade_in.xml b/core/res/res/anim/animator_fade_in.xml
deleted file mode 100644
index cff98cf..0000000
--- a/core/res/res/anim/animator_fade_in.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@interpolator/accelerate_quad"
- android:valueFrom="0"
- android:valueTo="1"
- android:propertyName="alpha"
- android:duration="@android:integer/config_mediumAnimTime"
-/>
diff --git a/core/res/res/anim/animator_fade_out.xml b/core/res/res/anim/animator_fade_out.xml
deleted file mode 100644
index 6a3d5ee..0000000
--- a/core/res/res/anim/animator_fade_out.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@interpolator/accelerate_quad"
- android:valueFrom="1.0"
- android:valueTo="0.0"
- android:propertyName="alpha"
- android:duration="@android:integer/config_mediumAnimTime"
-/>
diff --git a/core/res/res/anim/fragment_close_enter.xml b/core/res/res/anim/fragment_close_enter.xml
deleted file mode 100644
index c0abbc5..0000000
--- a/core/res/res/anim/fragment_close_enter.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:zAdjustment="normal">
- <objectAnimator
- android:interpolator="@interpolator/decelerate_quint"
- android:valueFrom="0.975" android:valueTo="1.0"
- android:valueType="floatType"
- android:propertyName="scaleY"
- android:duration="@android:integer/config_activityDefaultDur"/>
- <objectAnimator
- android:interpolator="@interpolator/decelerate_quint"
- android:valueFrom="0.975" android:valueTo="1.0"
- android:valueType="floatType"
- android:propertyName="scaleX"
- android:duration="@android:integer/config_activityDefaultDur"/>
- <objectAnimator
- android:interpolator="@interpolator/decelerate_cubic"
- android:valueFrom="0.0" android:valueTo="1.0"
- android:valueType="floatType"
- android:propertyName="alpha"
- android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_close_exit.xml b/core/res/res/anim/fragment_close_exit.xml
deleted file mode 100644
index 9a5708c..0000000
--- a/core/res/res/anim/fragment_close_exit.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:zAdjustment="top">
- <objectAnimator
- android:interpolator="@interpolator/decelerate_quint"
- android:valueFrom="1.0" android:valueTo="1.075"
- android:valueType="floatType"
- android:propertyName="scaleY"
- android:duration="@android:integer/config_activityDefaultDur"/>
- <objectAnimator
- android:interpolator="@interpolator/decelerate_quint"
- android:valueFrom="1.0" android:valueTo="1.075"
- android:valueType="floatType"
- android:propertyName="scaleX"
- android:duration="@android:integer/config_activityDefaultDur"/>
- <objectAnimator
- android:interpolator="@interpolator/decelerate_cubic"
- android:valueFrom="1.0" android:valueTo="0.0"
- android:valueType="floatType"
- android:propertyName="alpha"
- android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_enter.xml b/core/res/res/anim/fragment_next_enter.xml
deleted file mode 100644
index 13b15f3..0000000
--- a/core/res/res/anim/fragment_next_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:zAdjustment="top">
- <objectAnimator
- android:interpolator="@interpolator/decelerate_cubic"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType"
- android:propertyName="alpha"
- android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_exit.xml b/core/res/res/anim/fragment_next_exit.xml
deleted file mode 100644
index 503b7ad..0000000
--- a/core/res/res/anim/fragment_next_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:zAdjustment="normal">
- <objectAnimator
- android:interpolator="@interpolator/decelerate_cubic"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType"
- android:propertyName="alpha"
- android:duration="@android:integer/config_activityShortDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_enter.xml b/core/res/res/anim/fragment_open_enter.xml
deleted file mode 100644
index 6b16cb4..0000000
--- a/core/res/res/anim/fragment_open_enter.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
- <objectAnimator
- android:interpolator="@interpolator/decelerate_quint"
- android:valueFrom="1.125" android:valueTo="1.0"
- android:valueType="floatType"
- android:propertyName="scaleY"
- android:duration="@android:integer/config_activityDefaultDur"/>
- <objectAnimator
- android:interpolator="@interpolator/decelerate_quint"
- android:valueFrom="1.125" android:valueTo="1.0"
- android:valueType="floatType"
- android:propertyName="scaleX"
- android:duration="@android:integer/config_activityDefaultDur"/>
- <objectAnimator
- android:interpolator="@interpolator/decelerate_cubic"
- android:valueFrom="0.0" android:valueTo="1.0"
- android:valueType="floatType"
- android:propertyName="alpha"
- android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_exit.xml b/core/res/res/anim/fragment_open_exit.xml
deleted file mode 100644
index d77ee8e..0000000
--- a/core/res/res/anim/fragment_open_exit.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
- <objectAnimator
- android:interpolator="@interpolator/linear"
- android:valueFrom="1.0" android:valueTo="0.975"
- android:valueType="floatType"
- android:propertyName="scaleY"
- android:duration="@android:integer/config_activityDefaultDur"/>
- <objectAnimator
- android:interpolator="@interpolator/linear"
- android:valueFrom="1.0" android:valueTo="0.975"
- android:valueType="floatType"
- android:propertyName="scaleX"
- android:duration="@android:integer/config_activityDefaultDur"/>
- <objectAnimator
- android:interpolator="@interpolator/decelerate_cubic"
- android:valueFrom="1.0" android:valueTo="0.0"
- android:valueType="floatType"
- android:propertyName="alpha"
- android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_enter.xml b/core/res/res/anim/fragment_prev_enter.xml
deleted file mode 100644
index 13b15f3..0000000
--- a/core/res/res/anim/fragment_prev_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:zAdjustment="top">
- <objectAnimator
- android:interpolator="@interpolator/decelerate_cubic"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType"
- android:propertyName="alpha"
- android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_exit.xml b/core/res/res/anim/fragment_prev_exit.xml
deleted file mode 100644
index 503b7ad..0000000
--- a/core/res/res/anim/fragment_prev_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:zAdjustment="normal">
- <objectAnimator
- android:interpolator="@interpolator/decelerate_cubic"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType"
- android:propertyName="alpha"
- android:duration="@android:integer/config_activityShortDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fade_in.xml b/core/res/res/animator/fade_in.xml
index 2a28b4d..cff98cf 100644
--- a/core/res/res/animator/fade_in.xml
+++ b/core/res/res/animator/fade_in.xml
@@ -18,7 +18,7 @@
-->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@anim/accelerate_interpolator"
+ android:interpolator="@interpolator/accelerate_quad"
android:valueFrom="0"
android:valueTo="1"
android:propertyName="alpha"
diff --git a/core/res/res/animator/fade_out.xml b/core/res/res/animator/fade_out.xml
index 4db6591..6a3d5ee 100644
--- a/core/res/res/animator/fade_out.xml
+++ b/core/res/res/animator/fade_out.xml
@@ -18,7 +18,7 @@
-->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@anim/accelerate_interpolator"
+ android:interpolator="@interpolator/accelerate_quad"
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
diff --git a/core/res/res/drawable-hdpi/ic_menu_help.png b/core/res/res/drawable-hdpi/ic_menu_help.png
index 4300e86..01a77da 100644
--- a/core/res/res/drawable-hdpi/ic_menu_help.png
+++ b/core/res/res/drawable-hdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal.9.png b/core/res/res/drawable-mdpi/btn_default_normal.9.png
index a2d5ccd..7ff74b2 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
index edd3a3e..d3e11b5 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
index f506179..843ca7a 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
index 033bf89..74fd58b 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_selected.9.png b/core/res/res/drawable-mdpi/btn_default_selected.9.png
index 1e900bf..415b145 100644
--- a/core/res/res/drawable-mdpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
index bcedd5f..5dddd46 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
index ac6260f..6ab5c4a 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
index 4ee1b3f..c65bace 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
index 25e38f4..43e82f9 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
index cc209c6..7a376a9 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
index ccb010f..68ad039 100644
--- a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_help.png b/core/res/res/drawable-mdpi/ic_menu_help.png
index 7c55dfd..12ca235 100644
--- a/core/res/res/drawable-mdpi/ic_menu_help.png
+++ b/core/res/res/drawable-mdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 2e87883..1a6f404 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -91,7 +91,7 @@
<color name="search_url_text_selected">@android:color/black</color>
<color name="search_url_text_pressed">@android:color/black</color>
<color name="search_widget_corpus_item_background">@android:color/lighter_gray</color>
-
+
<!-- SlidingTab -->
<color name="sliding_tab_text_color_active">@android:color/black</color>
<color name="sliding_tab_text_color_shadow">@android:color/black</color>
@@ -105,7 +105,7 @@
<!-- keyguard clock -->
<color name="lockscreen_clock_background">#b3ffffff</color>
- <color name="lockscreen_clock_foreground">#40000000</color>
+ <color name="lockscreen_clock_foreground">#7affffff</color>
<color name="lockscreen_clock_am_pm">#ff9a9a9a</color>
<color name="lockscreen_owner_info">#ff9a9a9a</color>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c2a848d..e124d9d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1458,9 +1458,6 @@
sinusoidal pattern. -->
<public type="interpolator" name="cycle" />
- <public type="anim" name="animator_fade_in" />
- <public type="anim" name="animator_fade_out" />
-
<!-- Acceleration curve matching a cubic ease in function. -->
<public type="anim" name="accelerate_cubic_interpolator" />
<!-- Acceleration curve matching a cubic ease out function. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 96e60f2..920312b 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -81,14 +81,14 @@
<item name="wallpaperIntraOpenExitAnimation">@anim/wallpaper_intra_open_exit</item>
<item name="wallpaperIntraCloseEnterAnimation">@anim/wallpaper_intra_close_enter</item>
<item name="wallpaperIntraCloseExitAnimation">@anim/wallpaper_intra_close_exit</item>
- <item name="fragmentOpenEnterAnimation">@anim/fragment_open_enter</item>
- <item name="fragmentOpenExitAnimation">@anim/fragment_open_exit</item>
- <item name="fragmentCloseEnterAnimation">@anim/fragment_close_enter</item>
- <item name="fragmentCloseExitAnimation">@anim/fragment_close_exit</item>
- <item name="fragmentNextEnterAnimation">@anim/fragment_next_enter</item>
- <item name="fragmentNextExitAnimation">@anim/fragment_next_exit</item>
- <item name="fragmentPrevEnterAnimation">@anim/fragment_prev_enter</item>
- <item name="fragmentPrevExitAnimation">@anim/fragment_prev_exit</item>
+ <item name="fragmentOpenEnterAnimation">@animator/fragment_open_enter</item>
+ <item name="fragmentOpenExitAnimation">@animator/fragment_open_exit</item>
+ <item name="fragmentCloseEnterAnimation">@animator/fragment_close_enter</item>
+ <item name="fragmentCloseExitAnimation">@animator/fragment_close_exit</item>
+ <item name="fragmentNextEnterAnimation">@animator/fragment_next_enter</item>
+ <item name="fragmentNextExitAnimation">@animator/fragment_next_exit</item>
+ <item name="fragmentPrevEnterAnimation">@animator/fragment_prev_enter</item>
+ <item name="fragmentPrevExitAnimation">@animator/fragment_prev_exit</item>
</style>
<!-- Standard animations for a non-full-screen window or activity. -->
diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java
index 216a772..b5c2c27 100644
--- a/core/tests/coretests/src/android/util/JsonReaderTest.java
+++ b/core/tests/coretests/src/android/util/JsonReaderTest.java
@@ -16,11 +16,10 @@
package android.util;
-import java.util.Arrays;
-import junit.framework.TestCase;
-
import java.io.IOException;
import java.io.StringReader;
+import java.util.Arrays;
+import junit.framework.TestCase;
public final class JsonReaderTest extends TestCase {
@@ -677,7 +676,7 @@
try {
reader.nextString();
fail();
- } catch (IOException expected) {
+ } catch (MalformedJsonException expected) {
}
}
@@ -811,4 +810,50 @@
reader.nextNull();
reader.endArray();
}
+
+ public void testStrictMultipleTopLevelValues() throws IOException {
+ JsonReader reader = new JsonReader(new StringReader("[] []"));
+ reader.beginArray();
+ reader.endArray();
+ try {
+ reader.peek();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ public void testLenientMultipleTopLevelValues() throws IOException {
+ JsonReader reader = new JsonReader(new StringReader("[] true {}"));
+ reader.setLenient(true);
+ reader.beginArray();
+ reader.endArray();
+ assertEquals(true, reader.nextBoolean());
+ reader.beginObject();
+ reader.endObject();
+ assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+ }
+
+ public void testStrictTopLevelValueType() {
+ JsonReader reader = new JsonReader(new StringReader("true"));
+ try {
+ reader.nextBoolean();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ public void testLenientTopLevelValueType() throws IOException {
+ JsonReader reader = new JsonReader(new StringReader("true"));
+ reader.setLenient(true);
+ assertEquals(true, reader.nextBoolean());
+ }
+
+ public void testStrictNonExecutePrefix() {
+ JsonReader reader = new JsonReader(new StringReader(")]}'\n []"));
+ try {
+ reader.beginArray();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
}
diff --git a/core/tests/coretests/src/android/util/JsonWriterTest.java b/core/tests/coretests/src/android/util/JsonWriterTest.java
index fa84023..b29e2fd 100644
--- a/core/tests/coretests/src/android/util/JsonWriterTest.java
+++ b/core/tests/coretests/src/android/util/JsonWriterTest.java
@@ -16,10 +16,11 @@
package android.util;
-import junit.framework.TestCase;
-
import java.io.IOException;
import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import junit.framework.TestCase;
public final class JsonWriterTest extends TestCase {
@@ -119,7 +120,7 @@
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.beginObject();
jsonWriter.name("a");
- jsonWriter.value(null);
+ jsonWriter.value((String) null);
jsonWriter.endObject();
assertEquals("{\"a\":null}", stringWriter.toString());
}
@@ -145,6 +146,27 @@
}
}
+ public void testNonFiniteBoxedDoubles() throws IOException {
+ StringWriter stringWriter = new StringWriter();
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
+ jsonWriter.beginArray();
+ try {
+ jsonWriter.value(new Double(Double.NaN));
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ jsonWriter.value(new Double(Double.NEGATIVE_INFINITY));
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ jsonWriter.value(new Double(Double.POSITIVE_INFINITY));
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
public void testDoubles() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
@@ -189,6 +211,22 @@
+ "9223372036854775807]", stringWriter.toString());
}
+ public void testNumbers() throws IOException {
+ StringWriter stringWriter = new StringWriter();
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
+ jsonWriter.beginArray();
+ jsonWriter.value(new BigInteger("0"));
+ jsonWriter.value(new BigInteger("9223372036854775808"));
+ jsonWriter.value(new BigInteger("-9223372036854775809"));
+ jsonWriter.value(new BigDecimal("3.141592653589793238462643383"));
+ jsonWriter.endArray();
+ jsonWriter.close();
+ assertEquals("[0,"
+ + "9223372036854775808,"
+ + "-9223372036854775809,"
+ + "3.141592653589793238462643383]", stringWriter.toString());
+ }
+
public void testBooleans() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
diff --git a/data/fonts/AndroidClock.ttf b/data/fonts/AndroidClock.ttf
index 24a7f08..03e36cb 100644
--- a/data/fonts/AndroidClock.ttf
+++ b/data/fonts/AndroidClock.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf
index 1e14a8f..8fb31ba 100644
--- a/data/fonts/AndroidClock_Highlight.ttf
+++ b/data/fonts/AndroidClock_Highlight.ttf
Binary files differ
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 66c6d81..184620b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -85,8 +85,12 @@
@Override
protected void finalize() throws Throwable {
- if (mNativeCanvas != 0) {
- finalizer(mNativeCanvas);
+ try {
+ if (mNativeCanvas != 0) {
+ finalizer(mNativeCanvas);
+ }
+ } finally {
+ super.finalize();
}
}
}
@@ -137,6 +141,8 @@
* Returns null.
*
* @deprecated This method is not supported and should not be invoked.
+ *
+ * @hide
*/
@Deprecated
protected GL getGL() {
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 53962e1..7a47c3b 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -53,19 +53,6 @@
public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
- public enum CubemapLayout {
- VERTICAL_FACE_LIST (0),
- HORIZONTAL_FACE_LIST (1),
- VERTICAL_CROSS (2),
- HORIZONTAL_CROSS (3);
-
- int mID;
- CubemapLayout(int id) {
- mID = id;
- }
- }
-
-
public enum MipmapControl {
MIPMAP_NONE(0),
MIPMAP_FULL(1),
@@ -416,33 +403,41 @@
USAGE_GRAPHICS_TEXTURE);
}
+ /**
+ * Creates a cubemap allocation from a bitmap containing the
+ * horizontal list of cube faces. Each individual face must be
+ * the same size and power of 2
+ *
+ * @param rs
+ * @param b bitmap with cubemap faces layed out in the following
+ * format: right, left, top, bottom, front, back
+ * @param mips specifies desired mipmap behaviour for the cubemap
+ * @param usage bitfield specifying how the cubemap is utilized
+ *
+ **/
static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
MipmapControl mips,
- CubemapLayout layout,
int usage) {
rs.validate();
int height = b.getHeight();
int width = b.getWidth();
- if (layout != CubemapLayout.VERTICAL_FACE_LIST) {
- throw new RSIllegalArgumentException("Only vertical face list supported");
- }
- if (height % 6 != 0) {
+ if (width % 6 != 0) {
throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
}
- if (height / 6 != width) {
+ if (width / 6 != height) {
throw new RSIllegalArgumentException("Only square cobe map faces supported");
}
- boolean isPow2 = (width & (width - 1)) == 0;
+ boolean isPow2 = (height & (height - 1)) == 0;
if (!isPow2) {
throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
}
Element e = elementFromBitmap(rs, b);
Type.Builder tb = new Type.Builder(rs, e);
- tb.setX(width);
- tb.setY(width);
+ tb.setX(height);
+ tb.setY(height);
tb.setFaces(true);
tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
Type t = tb.create();
@@ -454,10 +449,9 @@
return new Allocation(id, rs, t, usage);
}
- static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
- CubemapLayout layout) {
+ static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b) {
return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
- layout, USAGE_GRAPHICS_TEXTURE);
+ USAGE_GRAPHICS_TEXTURE);
}
static public Allocation createFromBitmapResource(RenderScript rs,
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index ff92e08..cbc15d8 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -113,8 +113,11 @@
int mBufferCount;
// mCurrentTexture is the buffer slot index of the buffer that is currently
- // bound to the OpenGL texture. A value of INVALID_BUFFER_SLOT, indicating
- // that no buffer is currently bound to the texture.
+ // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
+ // indicating that no buffer slot is currently bound to the texture. Note,
+ // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+ // that no buffer is bound to the texture. A call to setBufferCount will
+ // reset mCurrentTexture to INVALID_BUFFER_SLOT.
int mCurrentTexture;
// mLastQueued is the buffer slot index of the most recently enqueued buffer.
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index b3815c4..4599d70 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -101,6 +101,8 @@
List<sp<AMessage> > mDeferredQueue;
+ bool mSentFormat;
+
status_t allocateBuffersOnPort(OMX_U32 portIndex);
status_t freeBuffersOnPort(OMX_U32 portIndex);
status_t freeBuffer(OMX_U32 portIndex, size_t i);
@@ -145,6 +147,8 @@
void deferMessage(const sp<AMessage> &msg);
void processDeferredMessages();
+ void sendFormatChange();
+
DISALLOW_EVIL_CONSTRUCTORS(ACodec);
};
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index 91ec60c..72dc730 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -52,6 +52,10 @@
void setObject(const char *name, const sp<RefBase> &obj);
void setMessage(const char *name, const sp<AMessage> &obj);
+ void setRect(
+ const char *name,
+ int32_t left, int32_t top, int32_t right, int32_t bottom);
+
bool findInt32(const char *name, int32_t *value) const;
bool findInt64(const char *name, int64_t *value) const;
bool findSize(const char *name, size_t *value) const;
@@ -62,6 +66,10 @@
bool findObject(const char *name, sp<RefBase> *obj) const;
bool findMessage(const char *name, sp<AMessage> *obj) const;
+ bool findRect(
+ const char *name,
+ int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const;
+
void post(int64_t delayUs = 0);
// Performs a deep-copy of "this", contained messages are in turn "dup'ed".
@@ -85,11 +93,16 @@
kTypeString,
kTypeObject,
kTypeMessage,
+ kTypeRect,
};
uint32_t mWhat;
ALooper::handler_id mTarget;
+ struct Rect {
+ int32_t mLeft, mTop, mRight, mBottom;
+ };
+
struct Item {
union {
int32_t int32Value;
@@ -100,6 +113,7 @@
void *ptrValue;
RefBase *refValue;
AString *stringValue;
+ Rect rectValue;
} u;
const char *mName;
Type mType;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 9579996..11a48d9 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_TAG "SurfaceTexture"
+//#define LOG_NDEBUG 0
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
@@ -36,21 +37,32 @@
SurfaceTexture::SurfaceTexture(GLuint tex) :
mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
mLastQueued(INVALID_BUFFER_SLOT), mTexName(tex) {
+ LOGV("SurfaceTexture::SurfaceTexture");
+ for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+ mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+ mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+ mSlots[i].mOwnedByClient = false;
+ }
}
SurfaceTexture::~SurfaceTexture() {
+ LOGV("SurfaceTexture::~SurfaceTexture");
freeAllBuffers();
}
status_t SurfaceTexture::setBufferCount(int bufferCount) {
+ LOGV("SurfaceTexture::setBufferCount");
Mutex::Autolock lock(mMutex);
freeAllBuffers();
mBufferCount = bufferCount;
+ mCurrentTexture = INVALID_BUFFER_SLOT;
+ mLastQueued = INVALID_BUFFER_SLOT;
return OK;
}
sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+ LOGV("SurfaceTexture::requestBuffer");
Mutex::Autolock lock(mMutex);
if (buf < 0 || mBufferCount <= buf) {
LOGE("requestBuffer: slot index out of range [0, %d]: %d",
@@ -75,6 +87,7 @@
}
status_t SurfaceTexture::dequeueBuffer(int *buf) {
+ LOGV("SurfaceTexture::dequeueBuffer");
Mutex::Autolock lock(mMutex);
int found = INVALID_BUFFER_SLOT;
for (int i = 0; i < mBufferCount; i++) {
@@ -92,6 +105,7 @@
}
status_t SurfaceTexture::queueBuffer(int buf) {
+ LOGV("SurfaceTexture::queueBuffer");
Mutex::Autolock lock(mMutex);
if (buf < 0 || mBufferCount <= buf) {
LOGE("queueBuffer: slot index out of range [0, %d]: %d",
@@ -111,6 +125,7 @@
}
void SurfaceTexture::cancelBuffer(int buf) {
+ LOGV("SurfaceTexture::cancelBuffer");
Mutex::Autolock lock(mMutex);
if (buf < 0 || mBufferCount <= buf) {
LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
@@ -124,18 +139,21 @@
}
status_t SurfaceTexture::setCrop(const Rect& reg) {
+ LOGV("SurfaceTexture::setCrop");
Mutex::Autolock lock(mMutex);
// XXX: How should we handle crops?
return OK;
}
status_t SurfaceTexture::setTransform(uint32_t transform) {
+ LOGV("SurfaceTexture::setTransform");
Mutex::Autolock lock(mMutex);
// XXX: How should we handle transforms?
return OK;
}
status_t SurfaceTexture::updateTexImage() {
+ LOGV("SurfaceTexture::updateTexImage");
Mutex::Autolock lock(mMutex);
// We always bind the texture even if we don't update its contents.
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 40dd117..406d09f 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -53,6 +53,10 @@
mDebugLevel = readDebugLevel();
LOGD("Enabling debug mode %d", mDebugLevel);
+
+#if RENDER_LAYERS_AS_REGIONS
+ LOGD("Layers will be composited as regions");
+#endif
}
Caches::~Caches() {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9613c5f..99bb6f0 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -162,6 +162,11 @@
GLenum status = GL_NO_ERROR;
while ((status = glGetError()) != GL_NO_ERROR) {
LOGD("GL error from OpenGLRenderer: 0x%x", status);
+ switch (status) {
+ case GL_OUT_OF_MEMORY:
+ LOGE(" OpenGLRenderer is out of memory!");
+ break;
+ }
}
#endif
#if DEBUG_MEMORY_USAGE
@@ -599,43 +604,23 @@
size_t count;
const android::Rect* rects = layer->region.getArray(&count);
- setupDraw();
-
- ProgramDescription description;
- description.hasTexture = true;
-
const float alpha = layer->alpha / 255.0f;
- const bool setColor = description.setColor(alpha, alpha, alpha, alpha);
- chooseBlending(layer->blend || layer->alpha < 255, layer->mode, description, false);
-
- useProgram(mCaches.programCache.get(description));
-
- // Texture
- bindTexture(layer->texture);
- glUniform1i(mCaches.currentProgram->getUniform("sampler"), 0);
-
- // Always premultiplied
- if (setColor) {
- mCaches.currentProgram->setColor(alpha, alpha, alpha, alpha);
- }
-
- // Mesh
- int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
- glEnableVertexAttribArray(texCoordsSlot);
-
- mModelView.loadIdentity();
- mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
-
const float texX = 1.0f / float(layer->width);
const float texY = 1.0f / float(layer->height);
TextureVertex* mesh = mCaches.getRegionMesh();
GLsizei numQuads = 0;
- glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
- gMeshStride, &mesh[0].position[0]);
- glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE,
- gMeshStride, &mesh[0].texture[0]);
+ setupDraw();
+ setupDrawWithTexture();
+ setupDrawColor(alpha, alpha, alpha, alpha);
+ setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
+ setupDrawProgram();
+ setupDrawDirtyRegionsDisabled();
+ setupDrawPureColorUniforms();
+ setupDrawTexture(layer->texture);
+ setupDrawModelViewIdentity();
+ setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0]);
for (size_t i = 0; i < count; i++) {
const android::Rect* r = &rects[i];
@@ -665,7 +650,7 @@
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glDisableVertexAttribArray(texCoordsSlot);
+ finishDrawTexture();
#if DEBUG_LAYERS_AS_REGIONS
uint32_t colors[] = {
@@ -1181,7 +1166,6 @@
}
void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
- // TODO: Should do quickReject for each line
if (mSnapshot->isIgnored()) return;
const bool isAA = paint->isAntiAlias();
@@ -1195,6 +1179,7 @@
getAlphaAndMode(paint, &alpha, &mode);
int verticesCount = count >> 2;
+ int generatedVerticesCount = 0;
if (!isHairLine) {
// TODO: AA needs more vertices
verticesCount *= 6;
@@ -1241,31 +1226,55 @@
vec2 p3 = b + n;
vec2 p4 = b - n;
- // Draw the line as 2 triangles, could be optimized
- // by using only 4 vertices and the correct indices
- // Also we should probably used non textured vertices
- // when line AA is disabled to save on bandwidth
- TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
- TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);
+ const float left = fmin(p1.x, fmin(p2.x, fmin(p3.x, p4.x)));
+ const float right = fmax(p1.x, fmax(p2.x, fmax(p3.x, p4.x)));
+ const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y)));
+ const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y)));
- // TODO: Mark the dirty regions when RENDER_LAYERS_AS_REGIONS is set
+ if (!quickReject(left, top, right, bottom)) {
+ // Draw the line as 2 triangles, could be optimized
+ // by using only 4 vertices and the correct indices
+ // Also we should probably used non textured vertices
+ // when line AA is disabled to save on bandwidth
+ TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
+ TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);
+
+ generatedVerticesCount += 6;
+
+ dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ }
}
- // GL_LINE does not give the result we want to match Skia
- glDrawArrays(GL_TRIANGLES, 0, verticesCount);
+ if (generatedVerticesCount > 0) {
+ // GL_LINE does not give the result we want to match Skia
+ glDrawArrays(GL_TRIANGLES, 0, generatedVerticesCount);
+ }
} else {
// TODO: Handle the AA case
for (int i = 0; i < count; i += 4) {
- TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
- TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
+ const float left = fmin(points[i], points[i + 1]);
+ const float right = fmax(points[i], points[i + 1]);
+ const float top = fmin(points[i + 2], points[i + 3]);
+ const float bottom = fmax(points[i + 2], points[i + 3]);
+
+ if (!quickReject(left, top, right, bottom)) {
+ TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
+ TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
+
+ generatedVerticesCount += 2;
+
+ dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ }
}
- glLineWidth(1.0f);
- glDrawArrays(GL_LINES, 0, verticesCount);
+ if (generatedVerticesCount > 0) {
+ glLineWidth(1.0f);
+ glDrawArrays(GL_LINES, 0, generatedVerticesCount);
+ }
}
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index c474936..6a0d7ea 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -26,7 +26,7 @@
*/
// If turned on, layers drawn inside FBOs are optimized with regions
-#define RENDER_LAYERS_AS_REGIONS 0
+#define RENDER_LAYERS_AS_REGIONS 1
/**
* Debug level for app developers.
diff --git a/libs/rs/java/Samples/res/drawable/cubemap_test.png b/libs/rs/java/Samples/res/drawable/cubemap_test.png
index 75ad0a4..baf35d0 100644
--- a/libs/rs/java/Samples/res/drawable/cubemap_test.png
+++ b/libs/rs/java/Samples/res/drawable/cubemap_test.png
Binary files differ
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java b/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
index 5430a13..1afcee3 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
@@ -22,7 +22,6 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.renderscript.*;
-import android.renderscript.Allocation.CubemapLayout;
import android.renderscript.Allocation.MipmapControl;
import android.renderscript.Program.TextureType;
import android.renderscript.ProgramStore.DepthFunc;
@@ -318,8 +317,7 @@
mTexTransparent = loadTextureARGB(R.drawable.leaf);
mTexChecker = loadTextureRGB(R.drawable.checker);
Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test);
- mTexCube = Allocation.createCubemapFromBitmap(mRS, b,
- Allocation.CubemapLayout.VERTICAL_FACE_LIST);
+ mTexCube = Allocation.createCubemapFromBitmap(mRS, b);
mScript.set_gTexTorus(mTexTorus);
mScript.set_gTexOpaque(mTexOpaque);
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index cac105a..87840a7 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -22,7 +22,6 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.renderscript.*;
-import android.renderscript.Allocation.CubemapLayout;
import android.renderscript.Font.Style;
import android.renderscript.Program.TextureType;
import android.renderscript.ProgramStore.DepthFunc;
@@ -308,8 +307,7 @@
mTexTransparent = loadTextureARGB(R.drawable.leaf);
mTexChecker = loadTextureRGB(R.drawable.checker);
Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test);
- mTexCube = Allocation.createCubemapFromBitmap(mRS, b,
- Allocation.CubemapLayout.VERTICAL_FACE_LIST);
+ mTexCube = Allocation.createCubemapFromBitmap(mRS, b);
mScript.set_gTexTorus(mTexTorus);
mScript.set_gTexOpaque(mTexOpaque);
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index a50321e..fc3a065 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -66,6 +66,7 @@
unitTests.add(new UT_primitives(this, mRes, mCtx));
unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+ unitTests.add(new UT_rstime(this, mRes, mCtx));
unitTests.add(new UT_rstypes(this, mRes, mCtx));
unitTests.add(new UT_fp_mad(this, mRes, mCtx));
/*
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..f302e1a
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,40 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+ private Resources mRes;
+
+ protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "rsTime", ctx);
+ mRes = res;
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime);
+ pRS.setMessageHandler(mRsMessage);
+ s.invoke_test_rstime(0, 0);
+ pRS.finish();
+ waitForMessage();
+ pRS.destroy();
+ }
+}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/rstime.rs b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..5e3e078
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+ bool failed = false;
+
+ rs_time_t curTime = rsTime(0);
+ rs_tm tm;
+ rsDebug("curTime", curTime);
+
+ rsLocaltime(&tm, &curTime);
+
+ rsDebug("tm.tm_sec", tm.tm_sec);
+ rsDebug("tm.tm_min", tm.tm_min);
+ rsDebug("tm.tm_hour", tm.tm_hour);
+ rsDebug("tm.tm_mday", tm.tm_mday);
+ rsDebug("tm.tm_mon", tm.tm_mon);
+ rsDebug("tm.tm_year", tm.tm_year);
+ rsDebug("tm.tm_wday", tm.tm_wday);
+ rsDebug("tm.tm_yday", tm.tm_yday);
+ rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+ // Test a specific time (only valid for PST localtime)
+ curTime = 1294438893;
+ rsLocaltime(&tm, &curTime);
+
+ _RS_ASSERT(tm.tm_sec == 33);
+ _RS_ASSERT(tm.tm_min == 21);
+ _RS_ASSERT(tm.tm_hour == 14);
+ _RS_ASSERT(tm.tm_mday == 7);
+ _RS_ASSERT(tm.tm_mon == 0);
+ _RS_ASSERT(tm.tm_year == 111);
+ _RS_ASSERT(tm.tm_wday == 5);
+ _RS_ASSERT(tm.tm_yday == 6);
+ _RS_ASSERT(tm.tm_isdst == 0);
+
+ return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+ bool failed = false;
+ failed |= basic_test(index);
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ rsDebug("rstime_test FAILED", -1);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ rsDebug("rstime_test PASSED", 0);
+ }
+}
+
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 3608e43..673ade2 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -831,16 +831,21 @@
return NULL;
}
+ uint32_t faceSize = t->getDimX();
+ uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes();
+ uint32_t copySize = faceSize * t->getElementSizeBytes();
+
uint8_t *sourcePtr = (uint8_t*)data;
for (uint32_t face = 0; face < 6; face ++) {
Adapter2D faceAdapter(rsc, texAlloc);
faceAdapter.setFace(face);
- size_t cpySize = t->getDimX() * t->getDimX() * t->getElementSizeBytes();
- memcpy(faceAdapter.getElement(0, 0), sourcePtr, cpySize);
+ for (uint32_t dI = 0; dI < faceSize; dI ++) {
+ memcpy(faceAdapter.getElement(0, dI), sourcePtr + strideBytes * dI, copySize);
+ }
// Move the data pointer to the next cube face
- sourcePtr += cpySize;
+ sourcePtr += copySize;
if (mips == RS_ALLOCATION_MIPMAP_FULL) {
Adapter2D adapt(rsc, texAlloc);
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 6a065b2..c5ee7ee 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -44,6 +44,7 @@
uint32_t Context::gThreadTLSKeyCount = 0;
uint32_t Context::gGLContextCount = 0;
pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
if (returnVal != EGL_TRUE) {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 3c402c4..df275bc 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -75,6 +75,8 @@
static uint32_t gThreadTLSKeyCount;
static uint32_t gGLContextCount;
static pthread_mutex_t gInitMutex;
+ // Library mutex (for providing thread-safe calls from the runtime)
+ static pthread_mutex_t gLibMutex;
struct ScriptTLSStruct {
Context * mContext;
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index f61b983..0b21669 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -100,70 +100,24 @@
// Time routines
//////////////////////////////////////////////////////////////////////////////
-static int32_t SC_second() {
+static time_t SC_time(time_t *timer) {
GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_sec;
+ return time(timer);
}
-static int32_t SC_minute() {
+static tm* SC_localtime(tm *local, time_t *timer) {
GET_TLS();
+ if (!local) {
+ return NULL;
+ }
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_min;
-}
-
-static int32_t SC_hour() {
- GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_hour;
-}
-
-static int32_t SC_day() {
- GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_mday;
-}
-
-static int32_t SC_month() {
- GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_mon;
-}
-
-static int32_t SC_year() {
- GET_TLS();
-
- time_t rawtime;
- time(&rawtime);
-
- struct tm *timeinfo;
- timeinfo = localtime(&rawtime);
- return timeinfo->tm_year;
+ // The native localtime function is not thread-safe, so we
+ // have to apply locking for proper behavior in RenderScript.
+ pthread_mutex_lock(&rsc->gLibMutex);
+ tm *tmp = localtime(timer);
+ memcpy(local, tmp, sizeof(*tmp));
+ pthread_mutex_unlock(&rsc->gLibMutex);
+ return local;
}
static int64_t SC_uptimeMillis() {
@@ -498,12 +452,8 @@
{ "_Z6rsFracf", (void *)&SC_frac, true },
// time
- { "_Z8rsSecondv", (void *)&SC_second, true },
- { "_Z8rsMinutev", (void *)&SC_minute, true },
- { "_Z6rsHourv", (void *)&SC_hour, true },
- { "_Z5rsDayv", (void *)&SC_day, true },
- { "_Z7rsMonthv", (void *)&SC_month, true },
- { "_Z6rsYearv", (void *)&SC_year, true },
+ { "_Z6rsTimePi", (void *)&SC_time, true },
+ { "_Z11rsLocaltimeP5rs_tmPKi", (void *)&SC_localtime, true },
{ "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis, true },
{ "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos, true },
{ "_Z7rsGetDtv", (void*)&SC_getDt, false },
diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh
index d059997..a74c0e0 100644
--- a/libs/rs/scriptc/rs_math.rsh
+++ b/libs/rs/scriptc/rs_math.rsh
@@ -118,32 +118,6 @@
extern float __attribute__((overloadable))
rsFrac(float);
-// time
-extern int32_t __attribute__((overloadable))
- rsSecond(void);
-extern int32_t __attribute__((overloadable))
- rsMinute(void);
-extern int32_t __attribute__((overloadable))
- rsHour(void);
-extern int32_t __attribute__((overloadable))
- rsDay(void);
-extern int32_t __attribute__((overloadable))
- rsMonth(void);
-extern int32_t __attribute__((overloadable))
- rsYear(void);
-
-// Return the current system clock in milliseconds
-extern int64_t __attribute__((overloadable))
- rsUptimeMillis(void);
-
-// Return the current system clock in nanoseconds
-extern int64_t __attribute__((overloadable))
- rsUptimeNanos(void);
-
-// Return the time in seconds since function was last called in this script.
-extern float __attribute__((overloadable))
- rsGetDt(void);
-
// Send a message back to the client. Will not block and returns true
// if the message was sendable and false if the fifo was full.
// A message ID is required. Data payload is optional.
diff --git a/libs/rs/scriptc/rs_time.rsh b/libs/rs/scriptc/rs_time.rsh
new file mode 100644
index 0000000..f1abed63
--- /dev/null
+++ b/libs/rs/scriptc/rs_time.rsh
@@ -0,0 +1,36 @@
+#ifndef __RS_TIME_RSH__
+#define __RS_TIME_RSH__
+
+typedef int rs_time_t;
+
+typedef struct {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+} rs_tm;
+
+extern rs_time_t __attribute__((overloadable))
+ rsTime(rs_time_t *timer);
+
+extern rs_tm * __attribute__((overloadable))
+ rsLocaltime(rs_tm *local, const rs_time_t *timer);
+
+// Return the current system clock in milliseconds
+extern int64_t __attribute__((overloadable))
+ rsUptimeMillis(void);
+
+// Return the current system clock in nanoseconds
+extern int64_t __attribute__((overloadable))
+ rsUptimeNanos(void);
+
+// Return the time in seconds since function was last called in this script.
+extern float __attribute__((overloadable))
+ rsGetDt(void);
+
+#endif
diff --git a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
index 4d4cd8d..802d1fb 100644
--- a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
+++ b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
@@ -309,6 +309,18 @@
realNotify->setInt32("width", width);
realNotify->setInt32("height", height);
+
+ int32_t cropLeft, cropTop, cropRight, cropBottom;
+ if (!meta->findRect(
+ kKeyCropRect,
+ &cropLeft, &cropTop, &cropRight, &cropBottom)) {
+ cropLeft = 0;
+ cropTop = 0;
+ cropRight = width - 1;
+ cropBottom = height - 1;
+ }
+
+ realNotify->setRect("crop", cropLeft, cropTop, cropRight, cropBottom);
}
notify->post();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e1b371e..7f534c0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -271,22 +271,43 @@
finishFlushIfPossible();
} else if (what == ACodec::kWhatOutputFormatChanged) {
- CHECK(audio);
+ if (audio) {
+ int32_t numChannels;
+ CHECK(codecRequest->findInt32("channel-count", &numChannels));
- int32_t numChannels;
- CHECK(codecRequest->findInt32("channel-count", &numChannels));
+ int32_t sampleRate;
+ CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
- int32_t sampleRate;
- CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
+ LOGV("Audio output format changed to %d Hz, %d channels",
+ sampleRate, numChannels);
- LOGV("Audio output format changed to %d Hz, %d channels",
- sampleRate, numChannels);
+ mAudioSink->close();
+ CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
+ mAudioSink->start();
- mAudioSink->close();
- CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
- mAudioSink->start();
+ mRenderer->signalAudioSinkChanged();
+ } else {
+ // video
- mRenderer->signalAudioSinkChanged();
+ int32_t width, height;
+ CHECK(codecRequest->findInt32("width", &width));
+ CHECK(codecRequest->findInt32("height", &height));
+
+ int32_t cropLeft, cropTop, cropRight, cropBottom;
+ CHECK(codecRequest->findRect(
+ "crop",
+ &cropLeft, &cropTop, &cropRight, &cropBottom));
+
+ LOGV("Video output format changed to %d x %d "
+ "(crop: %d, %d, %d, %d)",
+ width, height,
+ cropLeft, cropTop, cropRight, cropBottom);
+
+ notifyListener(
+ MEDIA_SET_VIDEO_SIZE,
+ cropRight - cropLeft + 1,
+ cropBottom - cropTop + 1);
+ }
} else if (what == ACodec::kWhatShutdownCompleted) {
LOGV("%s shutdown completed", audio ? "audio" : "video");
if (audio) {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 39e0c51..dfb4e00 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -299,7 +299,8 @@
////////////////////////////////////////////////////////////////////////////////
ACodec::ACodec()
- : mNode(NULL) {
+ : mNode(NULL),
+ mSentFormat(false) {
mUninitializedState = new UninitializedState(this);
mLoadedToIdleState = new LoadedToIdleState(this);
mIdleToExecutingState = new IdleToExecutingState(this);
@@ -980,6 +981,103 @@
}
}
+void ACodec::sendFormatChange() {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatOutputFormatChanged);
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ CHECK_EQ(mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
+ (status_t)OK);
+
+ CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
+
+ switch (def.eDomain) {
+ case OMX_PortDomainVideo:
+ {
+ OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
+
+ notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
+ notify->setInt32("width", videoDef->nFrameWidth);
+ notify->setInt32("height", videoDef->nFrameHeight);
+
+ OMX_CONFIG_RECTTYPE rect;
+ InitOMXParams(&rect);
+ rect.nPortIndex = kPortIndexOutput;
+
+ if (mOMX->getConfig(
+ mNode, OMX_IndexConfigCommonOutputCrop,
+ &rect, sizeof(rect)) != OK) {
+ rect.nLeft = 0;
+ rect.nTop = 0;
+ rect.nWidth = videoDef->nFrameWidth;
+ rect.nHeight = videoDef->nFrameHeight;
+ }
+
+ CHECK_GE(rect.nLeft, 0);
+ CHECK_GE(rect.nTop, 0);
+ CHECK_GE(rect.nWidth, 0u);
+ CHECK_GE(rect.nHeight, 0u);
+ CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
+ CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
+
+ notify->setRect(
+ "crop",
+ rect.nLeft,
+ rect.nTop,
+ rect.nLeft + rect.nWidth - 1,
+ rect.nTop + rect.nHeight - 1);
+
+ if (mNativeWindow != NULL) {
+ android_native_rect_t crop;
+ crop.left = rect.nLeft;
+ crop.top = rect.nTop;
+ crop.right = rect.nLeft + rect.nWidth - 1;
+ crop.bottom = rect.nTop + rect.nHeight - 1;
+
+ CHECK_EQ(0, native_window_set_crop(
+ mNativeWindow.get(), &crop));
+ }
+ break;
+ }
+
+ case OMX_PortDomainAudio:
+ {
+ OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
+ CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
+
+ OMX_AUDIO_PARAM_PCMMODETYPE params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = kPortIndexOutput;
+
+ CHECK_EQ(mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm,
+ ¶ms, sizeof(params)),
+ (status_t)OK);
+
+ CHECK(params.nChannels == 1 || params.bInterleaved);
+ CHECK_EQ(params.nBitPerSample, 16u);
+ CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
+ CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSamplingRate);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+
+ notify->post();
+
+ mSentFormat = true;
+}
+
////////////////////////////////////////////////////////////////////////////////
ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
@@ -1305,6 +1403,10 @@
info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
}
} else {
+ if (!mCodec->mSentFormat) {
+ mCodec->sendFormatChange();
+ }
+
if (mCodec->mNativeWindow == NULL) {
info->mData->setRange(rangeOffset, rangeLength);
}
@@ -1717,7 +1819,7 @@
{
CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
- if (data2 == OMX_IndexParamPortDefinition) {
+ if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
CHECK_EQ(mCodec->mOMX->sendCommand(
mCodec->mNode,
OMX_CommandPortDisable, kPortIndexOutput),
@@ -1729,6 +1831,8 @@
}
mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
+ } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
+ mCodec->mSentFormat = false;
} else {
LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
mCodec->mComponentName.c_str(), data2);
@@ -1816,6 +1920,8 @@
} else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
+ mCodec->mSentFormat = false;
+
LOGV("[%s] Output port now reenabled.",
mCodec->mComponentName.c_str());
@@ -1869,6 +1975,8 @@
void ACodec::ExecutingToIdleState::stateEntered() {
LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
+
+ mCodec->mSentFormat = false;
}
bool ACodec::ExecutingToIdleState::onOMXEvent(
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 9677838..31b6ec9 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -347,7 +347,8 @@
}
void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
- if (!mUseStillCameraForTimeLapse) {
+ if (!mUseStillCameraForTimeLapse &&
+ mCamera != NULL) {
mCamera->releaseRecordingFrame(frame);
}
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 7750a9d..e516cb4 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -3923,6 +3923,8 @@
if (!mIsEncoder) {
OMX_CONFIG_RECTTYPE rect;
+ InitOMXParams(&rect);
+ rect.nPortIndex = kPortIndexOutput;
status_t err =
mOMX->getConfig(
mNode, OMX_IndexConfigCommonOutputCrop,
diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
index 0f08f6e..38778fb 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
@@ -132,7 +132,10 @@
}
MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle);
- CHECK_EQ(mode, actualMode);
+ if (mode != actualMode) {
+ PVCleanUpVideoDecoder(mHandle);
+ return UNKNOWN_ERROR;
+ }
PVSetPostProcType((VideoDecControls *) mHandle, 0);
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 0e40acc..b592c3f 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -171,6 +171,18 @@
item->u.refValue = obj.get();
}
+void AMessage::setRect(
+ const char *name,
+ int32_t left, int32_t top, int32_t right, int32_t bottom) {
+ Item *item = allocateItem(name);
+ item->mType = kTypeRect;
+
+ item->u.rectValue.mLeft = left;
+ item->u.rectValue.mTop = top;
+ item->u.rectValue.mRight = right;
+ item->u.rectValue.mBottom = bottom;
+}
+
bool AMessage::findString(const char *name, AString *value) const {
const Item *item = findItem(name, kTypeString);
if (item) {
@@ -198,6 +210,22 @@
return false;
}
+bool AMessage::findRect(
+ const char *name,
+ int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
+ const Item *item = findItem(name, kTypeRect);
+ if (item == NULL) {
+ return false;
+ }
+
+ *left = item->u.rectValue.mLeft;
+ *top = item->u.rectValue.mTop;
+ *right = item->u.rectValue.mRight;
+ *bottom = item->u.rectValue.mBottom;
+
+ return true;
+}
+
void AMessage::post(int64_t delayUs) {
extern ALooperRoster gLooperRoster;
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index ed74cbe..66ccdae 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -76,6 +76,7 @@
#include <cmath>
#include <cstdlib>
#include <ctime>
+#include <iomanip>
#include <istream>
#include <libgen.h>
#include <list>
@@ -125,6 +126,7 @@
const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
// Global Constants
+const uint32_t printFieldWidth = 2;
const struct searchLimits {
uint32_t numOverlays;
HwcTestDim sourceCrop;
@@ -233,6 +235,8 @@
static EGLDisplay dpy;
static EGLSurface surface;
static EGLint width, height;
+static size_t maxHeadingLen;
+static vector<string> formats;
// Measurements
struct meas {
@@ -264,6 +268,9 @@
HwcTestDim vScaleBestDf;
HwcTestDim vScaleBestSc;
} sc;
+ vector<uint32_t> overlapBlendNone;
+ vector<uint32_t> overlapBlendPremult;
+ vector<uint32_t> overlapBlendCoverage;
};
vector<meas> measurements;
@@ -292,9 +299,14 @@
const HwcTestDim& dfMin, const HwcTestDim& dfMax,
const HwcTestDim& scMin, const HwcTestDim& scMax,
HwcTestDim& outBestDf, HwcTestDim& outBestSc);
+uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
+ uint32_t backgroundBlend, uint32_t foregroundBlend);
string transformList2str(const list<uint32_t>& transformList);
string blendList2str(const list<uint32_t>& blendList);
void init(void);
+void printFormatHeadings(size_t indent);
+void printOverlapLine(size_t indent, const string formatStr,
+ const vector<uint32_t>& results);
void printSyntax(const char *cmd);
// Command-line option settings
@@ -332,7 +344,6 @@
bool error;
string str;
char cmd[MAXCMD];
- list<string> formats;
list<Rectangle> rectList;
testSetLogCatTag(LOG_TAG);
@@ -395,6 +406,13 @@
}
}
+ // Determine length of longest specified graphic format.
+ // This value is used for output formating
+ for (vector<string>::iterator it = formats.begin();
+ it != formats.end(); ++it) {
+ maxHeadingLen = max(maxHeadingLen, it->length());
+ }
+
// Stop framework
rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
if (rv >= (signed) sizeof(cmd) - 1) {
@@ -411,7 +429,7 @@
init();
// For each of the graphic formats
- for (list<string>::iterator itFormat = formats.begin();
+ for (vector<string>::iterator itFormat = formats.begin();
itFormat != formats.end(); ++itFormat) {
// Locate hwcTestLib structure that describes this format
@@ -539,8 +557,66 @@
testPrintI(" VScale Best Source Crop: %s",
((string) measPtr->sc.vScaleBestSc).c_str());
+ // Overlap two graphic formats and different blends
+ // Results displayed after all overlap measurments with
+ // current format in the foreground
+ // TODO: make measurments with background blend other than
+ // none. All of these measurements are done with a
+ // background blend of HWC_BLENDING_NONE, with the
+ // blend type of the foregound being varied.
+ uint32_t foregroundFormat = format->format;
+ for (vector<string>::iterator it = formats.begin();
+ it != formats.end(); ++it) {
+ uint32_t num;
+
+ const struct hwcTestGraphicFormat *backgroundFormatPtr
+ = hwcTestGraphicFormatLookup((*it).c_str());
+ uint32_t backgroundFormat = backgroundFormatPtr->format;
+
+ num = numOverlapping(backgroundFormat, foregroundFormat,
+ HWC_BLENDING_NONE, HWC_BLENDING_NONE);
+ measPtr->overlapBlendNone.push_back(num);
+
+ num = numOverlapping(backgroundFormat, foregroundFormat,
+ HWC_BLENDING_NONE, HWC_BLENDING_PREMULT);
+ measPtr->overlapBlendPremult.push_back(num);
+
+ num = numOverlapping(backgroundFormat, foregroundFormat,
+ HWC_BLENDING_NONE, HWC_BLENDING_COVERAGE);
+ measPtr->overlapBlendCoverage.push_back(num);
+ }
+
}
+ // Display overlap results
+ size_t indent = 2;
+ testPrintI("overlapping blend: none");
+ printFormatHeadings(indent);
+ for (vector<string>::iterator it = formats.begin();
+ it != formats.end(); ++it) {
+ printOverlapLine(indent, *it, measurements[it
+ - formats.begin()].overlapBlendNone);
+ }
+ testPrintI("");
+
+ testPrintI("overlapping blend: premult");
+ printFormatHeadings(indent);
+ for (vector<string>::iterator it = formats.begin();
+ it != formats.end(); ++it) {
+ printOverlapLine(indent, *it, measurements[it
+ - formats.begin()].overlapBlendPremult);
+ }
+ testPrintI("");
+
+ testPrintI("overlapping blend: coverage");
+ printFormatHeadings(indent);
+ for (vector<string>::iterator it = formats.begin();
+ it != formats.end(); ++it) {
+ printOverlapLine(indent, *it, measurements[it
+ - formats.begin()].overlapBlendCoverage);
+ }
+ testPrintI("");
+
// Start framework
rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
if (rv >= (signed) sizeof(cmd) - 1) {
@@ -1204,6 +1280,33 @@
return best;
}
+uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
+ uint32_t backgroundBlend, uint32_t foregroundBlend)
+{
+ list<Rectangle> rectList;
+
+ Rectangle background(backgroundFormat, startDim, startDim);
+ background.blend = backgroundBlend;
+ rectList.push_back(background);
+
+ // TODO: Handle cases where startDim is so small that adding 5
+ // causes frames not to overlap.
+ // TODO: Handle cases where startDim is so large that adding 5
+ // cause a portion or all of the foreground displayFrame
+ // to be off the display.
+ Rectangle foreground(foregroundFormat, startDim, startDim);
+ foreground.displayFrame.left += 5;
+ foreground.displayFrame.top += 5;
+ foreground.displayFrame.right += 5;
+ foreground.displayFrame.bottom += 5;
+ background.blend = foregroundBlend;
+ rectList.push_back(foreground);
+
+ uint32_t num = numOverlays(rectList);
+
+ return num;
+}
+
Rectangle::Rectangle(uint32_t graphicFormat, HwcTestDim dfDim,
HwcTestDim sDim) :
format(graphicFormat), transform(defaultTransform),
@@ -1405,6 +1508,45 @@
hwcTestOpenHwc(&hwcDevice);
}
+void printFormatHeadings(size_t indent)
+{
+ for (size_t row = 0; row <= maxHeadingLen; row++) {
+ ostringstream line;
+ for(vector<string>::iterator it = formats.begin();
+ it != formats.end(); ++it) {
+ if ((maxHeadingLen - row) <= it->length()) {
+ if (row != maxHeadingLen) {
+ char ch = (*it)[it->length() - (maxHeadingLen - row)];
+ line << ' ' << setw(printFieldWidth) << ch;
+ } else {
+ line << ' ' << string(printFieldWidth, '-');
+ }
+ } else {
+ line << ' ' << setw(printFieldWidth) << "";
+ }
+ }
+ testPrintI("%*s%s", indent + maxHeadingLen, "",
+ line.str().c_str());
+ }
+}
+
+void printOverlapLine(size_t indent, const string formatStr,
+ const vector<uint32_t>& results)
+{
+ ostringstream line;
+
+ line << setw(indent + maxHeadingLen - formatStr.length()) << "";
+
+ line << formatStr;
+
+ for (vector<uint32_t>::const_iterator it = results.begin();
+ it != results.end(); ++it) {
+ line << ' ' << setw(printFieldWidth) << *it;
+ }
+
+ testPrintI("%s", line.str().c_str());
+}
+
void printSyntax(const char *cmd)
{
testPrintE(" %s [options] [graphicFormat] ...",
diff --git a/opengl/tests/hwc/hwcTestLib.cpp b/opengl/tests/hwc/hwcTestLib.cpp
index a468a92..925405e 100644
--- a/opengl/tests/hwc/hwcTestLib.cpp
+++ b/opengl/tests/hwc/hwcTestLib.cpp
@@ -475,14 +475,14 @@
testPrintI(" displayFrame: %s",
hwcTestRect2str(list->hwLayers[layer].displayFrame).c_str());
testPrintI(" scaleFactor: [%f, %f]",
- (float) (list->hwLayers[layer].displayFrame.right
- - list->hwLayers[layer].displayFrame.left)
- / (float) (list->hwLayers[layer].sourceCrop.right
- - list->hwLayers[layer].sourceCrop.left),
- (float) (list->hwLayers[layer].displayFrame.bottom
- - list->hwLayers[layer].displayFrame.top)
- / (float) (list->hwLayers[layer].sourceCrop.bottom
- - list->hwLayers[layer].sourceCrop.top));
+ (float) (list->hwLayers[layer].sourceCrop.right
+ - list->hwLayers[layer].sourceCrop.left)
+ / (float) (list->hwLayers[layer].displayFrame.right
+ - list->hwLayers[layer].displayFrame.left),
+ (float) (list->hwLayers[layer].sourceCrop.bottom
+ - list->hwLayers[layer].sourceCrop.top)
+ / (float) (list->hwLayers[layer].displayFrame.bottom
+ - list->hwLayers[layer].displayFrame.top));
}
}
@@ -494,7 +494,11 @@
*/
void hwcTestDisplayListPrepareModifiable(hwc_layer_list_t *list)
{
+ uint32_t numOverlays = 0;
for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
+ if (list->hwLayers[layer].compositionType == HWC_OVERLAY) {
+ numOverlays++;
+ }
testPrintI(" layer %u compositionType: %#x%s%s", layer,
list->hwLayers[layer].compositionType,
(list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
@@ -508,6 +512,7 @@
(list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
? " CLEAR_FB" : "");
}
+ testPrintI(" numOverlays: %u", numOverlays);
}
/*
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6e2bfdb..f8809d7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -262,11 +262,8 @@
// Watch for external modifications to the database file,
// keeping our cache in sync.
- // It's kinda lame to call mOpenHelper.getReadableDatabase()
- // during onCreate(), but since ensureAndroidIdIsSet has
- // already done it above and initialized/upgraded the
- // database, might as well just use it...
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.enableWriteAheadLogging();
sObserverInstance = new SettingsFileObserver(db.getPath());
sObserverInstance.startWatching();
startAsyncCachePopulation();
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d824f30..d3d1750 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -12,6 +12,7 @@
<application
android:persistent="true"
android:allowClearUserData="false"
+ android:hardwareAccelerated="true"
android:label="@string/app_label"
android:icon="@drawable/ic_launcher_settings">
diff --git a/packages/SystemUI/res/drawable-nodpi/panel_notification.png b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
index b0d9c18..437deff 100644
--- a/packages/SystemUI/res/drawable-nodpi/panel_notification.png
+++ b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/panel_notification_tiled.xml b/packages/SystemUI/res/drawable/panel_notification_tiled.xml
new file mode 100644
index 0000000..9d41e28
--- /dev/null
+++ b/packages/SystemUI/res/drawable/panel_notification_tiled.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<bitmap
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/panel_notification"
+ android:tileMode="repeat"
+ />
+
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
index d3fe2e7..7f84b21 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
@@ -20,27 +20,35 @@
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:orientation="vertical"
android:gravity="right"
- android:paddingTop="32dp"
>
- <LinearLayout
+ <View
+ android:id="@+id/scrim"
+ android:background="@drawable/notify_panel_bg_protect"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ />
+
+ <RelativeLayout
android:id="@+id/content_parent"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:animateLayoutChanges="true"
- android:orientation="vertical"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
>
-
- <com.android.systemui.statusbar.tablet.NotificationTitleArea
+ <RelativeLayout
android:id="@+id/title_area"
android:layout_height="160dp"
android:layout_width="384dp"
android:layout_marginLeft="24dp"
android:paddingTop="20dp"
android:orientation="vertical"
- android:animateLayoutChanges="true"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:background="@drawable/panel_notification_tiled"
>
<com.android.systemui.statusbar.tablet.HoloClock
@@ -154,13 +162,15 @@
android:src="@drawable/status_bar_veto"
android:baseline="21dp"
/>
- </com.android.systemui.statusbar.tablet.NotificationTitleArea>
+ </RelativeLayout>
<LinearLayout
android:id="@+id/content_frame"
android:layout_height="wrap_content"
android:layout_width="408dp"
android:orientation="vertical"
+ android:layout_below="@id/title_area"
+ android:layout_alignParentRight="true"
>
<ScrollView
android:id="@+id/notification_scroller"
@@ -191,5 +201,17 @@
android:src="@drawable/notify_item_glow_bottom"
/>
</LinearLayout>
- </LinearLayout>
+ </RelativeLayout>
+
+ <View
+ android:id="@+id/glow"
+ android:background="@drawable/notify_glow_back"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignTop="@id/content_parent"
+ android:layout_alignLeft="@id/content_parent"
+ android:layout_marginLeft="100dip"
+ android:layout_marginTop="-100dip"
+ />
+
</com.android.systemui.statusbar.tablet.NotificationPanel>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 7dcf9be..3201d06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.tablet;
import android.animation.Animator;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
@@ -33,11 +34,13 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.systemui.R;
-public class NotificationPanel extends LinearLayout implements StatusBarPanel,
+public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
View.OnClickListener {
static final String TAG = "Tablet/NotificationPanel";
static final boolean DEBUG = false;
@@ -51,12 +54,11 @@
ViewGroup mContentFrame;
Rect mContentArea;
View mSettingsView;
+ View mScrim, mGlow;
ViewGroup mContentParent;
Choreographer mChoreo = new Choreographer();
int mStatusBarHeight;
- Drawable mBgDrawable;
- Drawable mGlowDrawable;
public NotificationPanel(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -69,8 +71,6 @@
mStatusBarHeight = res.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
- mBgDrawable = res.getDrawable(R.drawable.notify_panel_bg_protect);
- mGlowDrawable = res.getDrawable(R.drawable.notify_glow_back);
}
@Override
@@ -80,9 +80,13 @@
setWillNotDraw(false);
mContentParent = (ViewGroup)findViewById(R.id.content_parent);
+ mContentParent.bringToFront();
mTitleArea = findViewById(R.id.title_area);
mTitleArea.setOnClickListener(this);
+ mScrim = findViewById(R.id.scrim);
+ mGlow = findViewById(R.id.glow);
+
mSettingsButton = (ImageView)findViewById(R.id.settings_button);
mNotificationButton = (ImageView)findViewById(R.id.notification_button);
@@ -132,21 +136,6 @@
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
- // We know that none of our children are GONE, so don't worry about skipping GONE views.
- final int N = getChildCount();
- if (N == 0) {
- return;
- }
- final int allocatedBottom = getChildAt(N-1).getBottom();
- final int shift = b - allocatedBottom - getPaddingBottom();
- if (shift <= 0) {
- return;
- }
- for (int i=0; i<N; i++) {
- final View c = getChildAt(i);
- c.layout(c.getLeft(), c.getTop() + shift, c.getRight(), c.getBottom() + shift);
- }
-
mChoreo.setPanelHeight(mContentParent.getHeight());
}
@@ -154,26 +143,6 @@
public void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mContentArea = null;
- mBgDrawable.setBounds(0, 0, w, h-mStatusBarHeight);
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- int saveCount;
- final int w = getWidth();
- final int h = getHeight();
-
- super.onDraw(canvas);
-
- // Background protection
- mBgDrawable.draw(canvas);
-
- // The panel glow (behind status bar)
-
- saveCount = canvas.save();
- canvas.clipRect(0, 0, w, h-mStatusBarHeight);
- mGlowDrawable.draw(canvas);
- canvas.restoreToCount(saveCount);
}
public void onClick(View v) {
@@ -227,82 +196,82 @@
private class Choreographer implements Animator.AnimatorListener {
boolean mVisible;
- int mBgAlpha;
- ValueAnimator mBgAnim;
int mPanelHeight;
- int mPanelBottom;
- ValueAnimator mPositionAnim;
+ AnimatorSet mContentAnim;
// should group this into a multi-property animation
- final int OPEN_DURATION = 200;
+ final int OPEN_DURATION = 250;
+
+ // the panel will start to appear this many px from the end
+ final int HYPERSPACE_OFFRAMP = 120;
Choreographer() {
}
- void createAnimation(boolean visible) {
- mBgAnim = ObjectAnimator.ofInt(this, "bgAlpha", mBgAlpha, visible ? 255 : 0)
- .setDuration(OPEN_DURATION);
- mBgAnim.addListener(this);
+ void createAnimation(boolean appearing) {
+ Animator bgAnim = ObjectAnimator.ofFloat(mScrim,
+ "alpha", mScrim.getAlpha(), appearing ? 1 : 0);
- mPositionAnim = ObjectAnimator.ofInt(this, "panelBottom", mPanelBottom,
- visible ? mPanelHeight : 0)
- .setDuration(OPEN_DURATION);
- }
+ float start, end;
- void startAnimation(boolean visible) {
- if (DEBUG) Slog.d(TAG, "startAnimation(visible=" + visible + ")");
-
- createAnimation(visible);
- mBgAnim.start();
- mPositionAnim.start();
-
- mVisible = visible;
- }
-
- void jumpTo(boolean visible) {
- setBgAlpha(visible ? 255 : 0);
- setPanelBottom(visible ? mPanelHeight : 0);
- }
-
- public void setBgAlpha(int alpha) {
- mBgAlpha = alpha;
- mBgDrawable.setAlpha((int)(alpha));
- invalidate();
- }
-
- // 0 is closed, the height of the panel is open
- public void setPanelBottom(int y) {
- mPanelBottom = y;
- int translationY = mPanelHeight - y;
- mContentParent.setTranslationY(translationY);
-
- final int glowXOffset = 100;
- final int glowYOffset = 100;
- int glowX = mContentParent.getLeft() - glowXOffset;
- int glowY = mContentParent.getTop() - glowYOffset + translationY;
- mGlowDrawable.setBounds(glowX, glowY, glowX + mGlowDrawable.getIntrinsicWidth(),
- glowY + mGlowDrawable.getIntrinsicHeight());
-
- float alpha;
- if (mPanelBottom > glowYOffset) {
- alpha = 1;
+ // 0: on-screen
+ // height: off-screen
+ float y = mContentParent.getTranslationY();
+ if (appearing) {
+ // we want to go from near-the-top to the top, unless we're half-open in the right
+ // general vicinity
+ start = (y < HYPERSPACE_OFFRAMP)
+ ? y
+ : HYPERSPACE_OFFRAMP;
+ end = 0;
} else {
- alpha = ((float)mPanelBottom) / glowYOffset;
+ start = y;
+ end = y + HYPERSPACE_OFFRAMP;
}
- mContentParent.setAlpha(alpha);
- mGlowDrawable.setAlpha((int)(255 * alpha));
+ Animator posAnim = ObjectAnimator.ofFloat(mContentParent, "translationY", start, end);
+ posAnim.setInterpolator(appearing
+ ? new android.view.animation.DecelerateInterpolator(2.0f)
+ : new android.view.animation.AccelerateInterpolator(2.0f));
- if (false) {
- Slog.d(TAG, "mPanelBottom=" + mPanelBottom + " translationY=" + translationY
- + " alpha=" + alpha + " glowY=" + glowY);
- }
+ Animator glowAnim = ObjectAnimator.ofFloat(mGlow, "alpha",
+ mGlow.getAlpha(), appearing ? 1.0f : 0.0f);
+ glowAnim.setInterpolator(appearing
+ ? new android.view.animation.AccelerateInterpolator(1.0f)
+ : new android.view.animation.DecelerateInterpolator(1.0f));
+
+ mContentAnim = new AnimatorSet();
+ mContentAnim
+ .play(ObjectAnimator.ofFloat(mContentParent, "alpha", mContentParent.getAlpha(),
+ appearing ? 1.0f : 0.0f))
+ .with(glowAnim)
+ .with(bgAnim)
+ .with(posAnim)
+ ;
+ mContentAnim.setDuration(OPEN_DURATION);
+ mContentAnim.addListener(this);
+ }
+
+ void startAnimation(boolean appearing) {
+ if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
+
+ createAnimation(appearing);
+
+ mContentParent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mContentAnim.start();
+
+ mVisible = appearing;
+ }
+
+ void jumpTo(boolean appearing) {
+// setBgAlpha(appearing ? 255 : 0);
+ mContentParent.setTranslationY(appearing ? 0 : mPanelHeight);
}
public void setPanelHeight(int h) {
+ if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
mPanelHeight = h;
- if (mPanelBottom == 0) {
+ if (mPanelHeight == 0) {
// fully closed, no animation necessary
- setPanelBottom(0);
} else if (mVisible) {
if (DEBUG) {
Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim to open fully");
@@ -312,17 +281,18 @@
}
public void onAnimationCancel(Animator animation) {
- if (DEBUG) Slog.d(TAG, "onAnimationCancel mBgAlpha=" + mBgAlpha);
+ if (DEBUG) Slog.d(TAG, "onAnimationCancel");
// force this to zero so we close the window
- mBgAlpha = 0;
+ mVisible = false;
}
public void onAnimationEnd(Animator animation) {
- if (DEBUG) Slog.d(TAG, "onAnimationEnd mBgAlpha=" + mBgAlpha);
- if (mBgAlpha == 0) {
+ if (DEBUG) Slog.d(TAG, "onAnimationEnd");
+ if (! mVisible) {
setVisibility(View.GONE);
}
- mBgAnim = null;
+ mContentParent.setLayerType(View.LAYER_TYPE_NONE, null);
+ mContentAnim = null;
}
public void onAnimationRepeat(Animator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java
deleted file mode 100644
index d4413db..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.systemui.statusbar.tablet;
-
-import android.content.Context;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.util.Slog;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-
-public class NotificationTitleArea extends RelativeLayout {
- static final String TAG = "NotificationTitleArea";
-
- View mSettingsButton;
- View mNotificationButton;
- View mNotificationScroller;
- FrameLayout mSettingsFrame;
- View mSettingsPanel;
-
- // for drawing the background
- Bitmap mTexture;
- Paint mPaint;
- int mTextureWidth;
- int mTextureHeight;
-
-
- public NotificationTitleArea(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public NotificationTitleArea(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- // for drawing the background
- mTexture = BitmapFactory.decodeResource(getResources(), R.drawable.panel_notification);
- mTextureWidth = mTexture.getWidth();
- mTextureHeight = mTexture.getHeight();
-
- mPaint = new Paint();
- mPaint.setDither(false);
- }
-
- public void onFinishInflate() {
- super.onFinishInflate();
- setWillNotDraw(false);
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- final Bitmap texture = mTexture;
- final Paint paint = mPaint;
-
- final int width = getWidth();
- final int height = getHeight();
-
- final int textureWidth = mTextureWidth;
- final int textureHeight = mTextureHeight;
-
- int x = 0;
- int y;
-
- while (x < width) {
- y = 0;
- while (y < height) {
- canvas.drawBitmap(texture, x, y, paint);
- y += textureHeight;
- }
- x += textureWidth;
- }
- }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index 612427b..53c30fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -252,7 +252,11 @@
private void refreshApplicationList() {
mActivityDescriptions = getRecentTasks();
- updateUiElements(getResources().getConfiguration(), true);
+ if (mActivityDescriptions.size() > 0) {
+ updateUiElements(getResources().getConfiguration(), true);
+ } else {
+ mBar.animateCollapse();
+ }
}
private Bitmap compositeBitmap(Bitmap background, Bitmap thumbnail) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 9ddb432..cd39d71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -183,7 +183,7 @@
mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
+ 720, // ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
@@ -196,6 +196,7 @@
lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
+// lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 2fcd04e..38eed50 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -26,9 +26,11 @@
import com.android.internal.view.BaseSurfaceHolder;
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
+import com.android.internal.view.menu.ActionMenuView;
import com.android.internal.view.menu.ContextMenuBuilder;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuDialogHelper;
+import com.android.internal.view.menu.MenuItemImpl;
import com.android.internal.view.menu.MenuPopupHelper;
import com.android.internal.view.menu.MenuView;
import com.android.internal.view.menu.SubMenuBuilder;
@@ -881,12 +883,16 @@
// The window manager will give us a valid window token
new MenuDialogHelper(subMenu).show(null);
} else if (hasFeature(FEATURE_ACTION_BAR)) {
- mActionButtonPopup = new ActionButtonSubmenu(getContext(), subMenu);
- mActionButtonPopup.show();
- Callback cb = getCallback();
- if (cb != null) {
- cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
- }
+ mDecor.post(new Runnable() {
+ public void run() {
+ mActionButtonPopup = new ActionButtonSubmenu(getContext(), subMenu);
+ mActionButtonPopup.show();
+ Callback cb = getCallback();
+ if (cb != null) {
+ cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
+ }
+ }
+ });
}
return true;
@@ -3009,6 +3015,20 @@
public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) {
super(context, subMenu);
mSubMenu = subMenu;
+
+ MenuBuilder parentMenu = subMenu.getRootMenu();
+ MenuItemImpl item = (MenuItemImpl) subMenu.getItem();
+ if (!item.isActionButton()) {
+ // Give a reasonable anchor to nested submenus.
+ ActionMenuView amv = (ActionMenuView) parentMenu.getMenuView(
+ MenuBuilder.TYPE_ACTION_BUTTON, null);
+
+ View anchor = amv.getOverflowButton();
+ if (anchor == null) {
+ anchor = amv;
+ }
+ setAnchorView(anchor);
+ }
}
@Override
diff --git a/services/input/Android.mk b/services/input/Android.mk
index 37804ff..d7b61fc 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -21,6 +21,7 @@
InputDispatcher.cpp \
InputManager.cpp \
InputReader.cpp \
+ InputWindow.cpp \
PointerController.cpp
LOCAL_SHARED_LIBRARIES := \
diff --git a/services/input/InputApplication.h b/services/input/InputApplication.h
new file mode 100644
index 0000000..cc80062
--- /dev/null
+++ b/services/input/InputApplication.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _UI_INPUT_APPLICATION_H
+#define _UI_INPUT_APPLICATION_H
+
+#include <ui/Input.h>
+
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/*
+ * A handle to an application that can receive input.
+ * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * that describe an application.
+ */
+class InputApplicationHandle : public RefBase {
+protected:
+ InputApplicationHandle() { }
+ virtual ~InputApplicationHandle() { }
+};
+
+
+/*
+ * An input application describes properties of an application that can receive input.
+ */
+struct InputApplication {
+ sp<InputApplicationHandle> inputApplicationHandle;
+ String8 name;
+ nsecs_t dispatchingTimeout;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_APPLICATION_H
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 89a7751..b5a4bd2 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -72,6 +72,10 @@
// when an application takes too long to respond and the user has pressed an app switch key.
const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
+// Amount of time to allow for an event to be dispatched (measured since its eventTime)
+// before considering it stale and dropping it.
+const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
+
static inline nsecs_t now() {
return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -151,34 +155,12 @@
}
-// --- InputWindow ---
-
-bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
- return x >= touchableAreaLeft && x <= touchableAreaRight
- && y >= touchableAreaTop && y <= touchableAreaBottom;
-}
-
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
- return x >= frameLeft && x <= frameRight
- && y >= frameTop && y <= frameBottom;
-}
-
-bool InputWindow::isTrustedOverlay() const {
- return layoutParamsType == TYPE_INPUT_METHOD
- || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
- || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
-}
-
-bool InputWindow::supportsSplitTouch() const {
- return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
-}
-
-
// --- InputDispatcher ---
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
mPolicy(policy),
- mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
+ mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
+ mNextUnblockedEvent(NULL),
mDispatchEnabled(true), mDispatchFrozen(false),
mFocusedWindow(NULL),
mFocusedApplication(NULL),
@@ -368,6 +350,7 @@
}
// Now we have an event to dispatch.
+ // All events are eventually dequeued and processed this way, even if we intend to drop them.
assert(mPendingEvent != NULL);
bool done = false;
DropReason dropReason = DROP_REASON_NOT_DROPPED;
@@ -376,6 +359,11 @@
} else if (!mDispatchEnabled) {
dropReason = DROP_REASON_DISABLED;
}
+
+ if (mNextUnblockedEvent == mPendingEvent) {
+ mNextUnblockedEvent = NULL;
+ }
+
switch (mPendingEvent->type) {
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
@@ -395,6 +383,13 @@
dropReason = DROP_REASON_APP_SWITCH;
}
}
+ if (dropReason == DROP_REASON_NOT_DROPPED
+ && isStaleEventLocked(currentTime, typedEntry)) {
+ dropReason = DROP_REASON_STALE;
+ }
+ if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+ dropReason = DROP_REASON_BLOCKED;
+ }
done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
&dropReason, nextWakeupTime);
break;
@@ -405,6 +400,13 @@
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
dropReason = DROP_REASON_APP_SWITCH;
}
+ if (dropReason == DROP_REASON_NOT_DROPPED
+ && isStaleEventLocked(currentTime, typedEntry)) {
+ dropReason = DROP_REASON_STALE;
+ }
+ if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+ dropReason = DROP_REASON_BLOCKED;
+ }
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
@@ -431,6 +433,9 @@
switch (entry->type) {
case EventEntry::TYPE_KEY: {
+ // Optimize app switch latency.
+ // If the application takes too long to catch up then we drop all events preceding
+ // the app switch key.
KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
if (isAppSwitchKeyEventLocked(keyEntry)) {
if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
@@ -448,11 +453,63 @@
}
break;
}
+
+ case EventEntry::TYPE_MOTION: {
+ // Optimize case where the current application is unresponsive and the user
+ // decides to touch a window in a different application.
+ // If the application takes too long to catch up then we drop all events preceding
+ // the touch into the other window.
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+ if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
+ && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
+ && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
+ && mInputTargetWaitApplication != NULL) {
+ int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].x);
+ int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].y);
+ const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
+ if (touchedWindow
+ && touchedWindow->inputWindowHandle != NULL
+ && touchedWindow->inputWindowHandle->getInputApplicationHandle()
+ != mInputTargetWaitApplication) {
+ // User touched a different application than the one we are waiting on.
+ // Flag the event, and start pruning the input queue.
+ mNextUnblockedEvent = motionEntry;
+ needWake = true;
+ }
+ }
+ break;
+ }
}
return needWake;
}
+const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
+ // Traverse windows from front to back to find touched window.
+ size_t numWindows = mWindows.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const InputWindow* window = & mWindows.editItemAt(i);
+ int32_t flags = window->layoutParamsFlags;
+
+ if (window->visible) {
+ if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
+ bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
+ | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
+ if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
+ // Found window.
+ return window;
+ }
+ }
+ }
+
+ if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
+ // Error window is on top but not visible, so touch is dropped.
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
const char* reason;
switch (dropReason) {
@@ -470,6 +527,16 @@
LOGI("Dropped event because of pending overdue app switch.");
reason = "inbound event was dropped because of pending overdue app switch";
break;
+ case DROP_REASON_BLOCKED:
+ LOGI("Dropped event because the current application is not responding and the user "
+ "has started interating with a different application.");
+ reason = "inbound event was dropped because the current application is not responding "
+ "and the user has started interating with a different application";
+ break;
+ case DROP_REASON_STALE:
+ LOGI("Dropped event because it is stale.");
+ reason = "inbound event was dropped because it is stale";
+ break;
default:
assert(false);
return;
@@ -521,6 +588,10 @@
#endif
}
+bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
+ return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
+}
+
bool InputDispatcher::runCommandsLockedInterruptible() {
if (mCommandQueue.isEmpty()) {
return false;
@@ -670,7 +741,7 @@
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
if (mFocusedWindow) {
- commandEntry->inputChannel = mFocusedWindow->inputChannel;
+ commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
@@ -848,6 +919,7 @@
mCurrentInputTargetsValid = false;
mCurrentInputTargets.clear();
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
+ mInputTargetWaitApplication.clear();
}
void InputDispatcher::commitTargetsLocked() {
@@ -866,6 +938,7 @@
mInputTargetWaitStartTime = currentTime;
mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
mInputTargetWaitTimeoutExpired = false;
+ mInputTargetWaitApplication.clear();
}
} else {
if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
@@ -880,6 +953,15 @@
mInputTargetWaitStartTime = currentTime;
mInputTargetWaitTimeoutTime = currentTime + timeout;
mInputTargetWaitTimeoutExpired = false;
+ mInputTargetWaitApplication.clear();
+
+ if (window && window->inputWindowHandle != NULL) {
+ mInputTargetWaitApplication =
+ window->inputWindowHandle->getInputApplicationHandle();
+ }
+ if (mInputTargetWaitApplication == NULL && application) {
+ mInputTargetWaitApplication = application->inputApplicationHandle;
+ }
}
}
@@ -2624,7 +2706,7 @@
void InputDispatcher::releaseFocusedApplicationLocked() {
if (mFocusedApplication) {
mFocusedApplication = NULL;
- mFocusedApplicationStorage.handle.clear();
+ mFocusedApplicationStorage.inputApplicationHandle.clear();
}
}
@@ -2860,7 +2942,8 @@
}
}
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
#if DEBUG_REGISTRATION
LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
toString(monitor));
@@ -2875,7 +2958,7 @@
return BAD_VALUE;
}
- sp<Connection> connection = new Connection(inputChannel);
+ sp<Connection> connection = new Connection(inputChannel, inputWindowHandle);
status_t status = connection->initialize();
if (status) {
LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
@@ -3002,9 +3085,10 @@
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doNotifyANRLockedInterruptible);
if (application) {
- commandEntry->inputApplicationHandle = application->handle;
+ commandEntry->inputApplicationHandle = application->inputApplicationHandle;
}
if (window) {
+ commandEntry->inputWindowHandle = window->inputWindowHandle;
commandEntry->inputChannel = window->inputChannel;
}
}
@@ -3025,7 +3109,7 @@
if (connection->status != Connection::STATUS_ZOMBIE) {
mLock.unlock();
- mPolicy->notifyInputChannelBroken(connection->inputChannel);
+ mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
mLock.lock();
}
@@ -3036,7 +3120,7 @@
mLock.unlock();
nsecs_t newTimeout = mPolicy->notifyANR(
- commandEntry->inputApplicationHandle, commandEntry->inputChannel);
+ commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);
mLock.lock();
@@ -3052,7 +3136,7 @@
mLock.unlock();
- bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
+ bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
&event, entry->policyFlags);
mLock.lock();
@@ -3095,7 +3179,7 @@
mLock.unlock();
- bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
+ bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
&event, keyEntry->policyFlags, &event);
mLock.lock();
@@ -3604,8 +3688,10 @@
// --- InputDispatcher::Connection ---
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
- status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle) :
+ status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
+ inputPublisher(inputChannel),
lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
}
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index c8beab2..11e5117 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -33,6 +33,9 @@
#include <unistd.h>
#include <limits.h>
+#include "InputWindow.h"
+#include "InputApplication.h"
+
namespace android {
@@ -116,137 +119,6 @@
/*
- * An input window describes the bounds of a window that can receive input.
- */
-struct InputWindow {
- // Window flags from WindowManager.LayoutParams
- enum {
- FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
- FLAG_DIM_BEHIND = 0x00000002,
- FLAG_BLUR_BEHIND = 0x00000004,
- FLAG_NOT_FOCUSABLE = 0x00000008,
- FLAG_NOT_TOUCHABLE = 0x00000010,
- FLAG_NOT_TOUCH_MODAL = 0x00000020,
- FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
- FLAG_KEEP_SCREEN_ON = 0x00000080,
- FLAG_LAYOUT_IN_SCREEN = 0x00000100,
- FLAG_LAYOUT_NO_LIMITS = 0x00000200,
- FLAG_FULLSCREEN = 0x00000400,
- FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
- FLAG_DITHER = 0x00001000,
- FLAG_SECURE = 0x00002000,
- FLAG_SCALED = 0x00004000,
- FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
- FLAG_LAYOUT_INSET_DECOR = 0x00010000,
- FLAG_ALT_FOCUSABLE_IM = 0x00020000,
- FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
- FLAG_SHOW_WHEN_LOCKED = 0x00080000,
- FLAG_SHOW_WALLPAPER = 0x00100000,
- FLAG_TURN_SCREEN_ON = 0x00200000,
- FLAG_DISMISS_KEYGUARD = 0x00400000,
- FLAG_SPLIT_TOUCH = 0x00800000,
- FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
- FLAG_COMPATIBLE_WINDOW = 0x20000000,
- FLAG_SYSTEM_ERROR = 0x40000000,
- };
-
- // Window types from WindowManager.LayoutParams
- enum {
- FIRST_APPLICATION_WINDOW = 1,
- TYPE_BASE_APPLICATION = 1,
- TYPE_APPLICATION = 2,
- TYPE_APPLICATION_STARTING = 3,
- LAST_APPLICATION_WINDOW = 99,
- FIRST_SUB_WINDOW = 1000,
- TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
- TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
- TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
- TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
- TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
- LAST_SUB_WINDOW = 1999,
- FIRST_SYSTEM_WINDOW = 2000,
- TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
- TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
- TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
- TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
- TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
- TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
- TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
- TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
- TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
- TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
- TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
- TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
- TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
- TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
- TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+14,
- TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
- TYPE_DRAG = FIRST_SYSTEM_WINDOW+16,
- TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+17,
- LAST_SYSTEM_WINDOW = 2999,
- };
-
- sp<InputChannel> inputChannel;
- String8 name;
- int32_t layoutParamsFlags;
- int32_t layoutParamsType;
- nsecs_t dispatchingTimeout;
- int32_t frameLeft;
- int32_t frameTop;
- int32_t frameRight;
- int32_t frameBottom;
- int32_t visibleFrameLeft;
- int32_t visibleFrameTop;
- int32_t visibleFrameRight;
- int32_t visibleFrameBottom;
- int32_t touchableAreaLeft;
- int32_t touchableAreaTop;
- int32_t touchableAreaRight;
- int32_t touchableAreaBottom;
- bool visible;
- bool canReceiveKeys;
- bool hasFocus;
- bool hasWallpaper;
- bool paused;
- int32_t layer;
- int32_t ownerPid;
- int32_t ownerUid;
-
- bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
- bool frameContainsPoint(int32_t x, int32_t y) const;
-
- /* Returns true if the window is of a trusted type that is allowed to silently
- * overlay other windows for the purpose of implementing the secure views feature.
- * Trusted overlays, such as IME windows, can partly obscure other windows without causing
- * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
- */
- bool isTrustedOverlay() const;
-
- bool supportsSplitTouch() const;
-};
-
-
-/*
- * A private handle type used by the input manager to track the window.
- */
-class InputApplicationHandle : public RefBase {
-protected:
- InputApplicationHandle() { }
- virtual ~InputApplicationHandle() { }
-};
-
-
-/*
- * An input application describes properties of an application that can receive input.
- */
-struct InputApplication {
- String8 name;
- nsecs_t dispatchingTimeout;
- sp<InputApplicationHandle> handle;
-};
-
-
-/*
* Input dispatcher policy interface.
*
* The input reader policy is used by the input reader to interact with the Window Manager
@@ -267,10 +139,10 @@
/* Notifies the system that an application is not responding.
* Returns a new timeout to continue waiting, or 0 to abort dispatch. */
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel) = 0;
+ const sp<InputWindowHandle>& inputWindowHandle) = 0;
/* Notifies the system that an input channel is unrecoverably broken. */
- virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
+ virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
/* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
virtual nsecs_t getKeyRepeatTimeout() = 0;
@@ -303,12 +175,12 @@
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
/* Allows the policy a chance to intercept a key before dispatching. */
- virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+ virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
/* Allows the policy a chance to perform default processing for an unhandled key.
* Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
- virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+ virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
/* Notifies the policy about switch events.
@@ -407,7 +279,8 @@
*
* These methods may be called on any thread (usually by the input manager).
*/
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) = 0;
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0;
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
};
@@ -461,7 +334,8 @@
virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel);
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
private:
@@ -615,6 +489,7 @@
KeyEntry* keyEntry;
sp<InputChannel> inputChannel;
sp<InputApplicationHandle> inputApplicationHandle;
+ sp<InputWindowHandle> inputWindowHandle;
int32_t userActivityEventType;
bool handled;
};
@@ -815,7 +690,8 @@
};
Status status;
- sp<InputChannel> inputChannel;
+ sp<InputChannel> inputChannel; // never null
+ sp<InputWindowHandle> inputWindowHandle; // may be null
InputPublisher inputPublisher;
InputState inputState;
Queue<DispatchEntry> outboundQueue;
@@ -823,7 +699,8 @@
nsecs_t lastEventTime; // the time when the event was originally captured
nsecs_t lastDispatchTime; // the time when the last event was dispatched
- explicit Connection(const sp<InputChannel>& inputChannel);
+ explicit Connection(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle);
inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
@@ -851,6 +728,8 @@
DROP_REASON_POLICY = 1,
DROP_REASON_APP_SWITCH = 2,
DROP_REASON_DISABLED = 3,
+ DROP_REASON_BLOCKED = 4,
+ DROP_REASON_STALE = 5,
};
sp<InputDispatcherPolicyInterface> mPolicy;
@@ -884,6 +763,15 @@
bool isAppSwitchPendingLocked();
void resetPendingAppSwitchLocked(bool handled);
+ // Stale event latency optimization.
+ static bool isStaleEventLocked(nsecs_t currentTime, EventEntry* entry);
+
+ // Blocked event latency optimization. Drops old events when the user intends
+ // to transfer focus to a new application.
+ EventEntry* mNextUnblockedEvent;
+
+ const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y);
+
// All registered connections mapped by receive pipe file descriptor.
KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
@@ -1006,6 +894,7 @@
nsecs_t mInputTargetWaitStartTime;
nsecs_t mInputTargetWaitTimeoutTime;
bool mInputTargetWaitTimeoutExpired;
+ sp<InputApplicationHandle> mInputTargetWaitApplication;
// Finding targets for input events.
void resetTargetsLocked();
diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp
new file mode 100644
index 0000000..9ce45f5
--- /dev/null
+++ b/services/input/InputWindow.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindow"
+
+#include "InputWindow.h"
+
+#include <cutils/log.h>
+
+namespace android {
+
+// --- InputWindow ---
+
+bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
+ return x >= touchableAreaLeft && x <= touchableAreaRight
+ && y >= touchableAreaTop && y <= touchableAreaBottom;
+}
+
+bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
+ return x >= frameLeft && x <= frameRight
+ && y >= frameTop && y <= frameBottom;
+}
+
+bool InputWindow::isTrustedOverlay() const {
+ return layoutParamsType == TYPE_INPUT_METHOD
+ || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
+ || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
+}
+
+bool InputWindow::supportsSplitTouch() const {
+ return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
+}
+
+} // namespace android
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
new file mode 100644
index 0000000..b3d5a65
--- /dev/null
+++ b/services/input/InputWindow.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _UI_INPUT_WINDOW_H
+#define _UI_INPUT_WINDOW_H
+
+#include <ui/Input.h>
+#include <ui/InputTransport.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/String8.h>
+
+#include "InputApplication.h"
+
+namespace android {
+
+/*
+ * A handle to a window that can receive input.
+ * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * that describe a window.
+ */
+class InputWindowHandle : public RefBase {
+protected:
+ InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+ mInputApplicationHandle(inputApplicationHandle) { }
+ virtual ~InputWindowHandle() { }
+
+public:
+ inline sp<InputApplicationHandle> getInputApplicationHandle() {
+ return mInputApplicationHandle;
+ }
+
+private:
+ sp<InputApplicationHandle> mInputApplicationHandle;
+};
+
+
+/*
+ * An input window describes the bounds of a window that can receive input.
+ */
+struct InputWindow {
+ // Window flags from WindowManager.LayoutParams
+ enum {
+ FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
+ FLAG_DIM_BEHIND = 0x00000002,
+ FLAG_BLUR_BEHIND = 0x00000004,
+ FLAG_NOT_FOCUSABLE = 0x00000008,
+ FLAG_NOT_TOUCHABLE = 0x00000010,
+ FLAG_NOT_TOUCH_MODAL = 0x00000020,
+ FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
+ FLAG_KEEP_SCREEN_ON = 0x00000080,
+ FLAG_LAYOUT_IN_SCREEN = 0x00000100,
+ FLAG_LAYOUT_NO_LIMITS = 0x00000200,
+ FLAG_FULLSCREEN = 0x00000400,
+ FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
+ FLAG_DITHER = 0x00001000,
+ FLAG_SECURE = 0x00002000,
+ FLAG_SCALED = 0x00004000,
+ FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
+ FLAG_LAYOUT_INSET_DECOR = 0x00010000,
+ FLAG_ALT_FOCUSABLE_IM = 0x00020000,
+ FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
+ FLAG_SHOW_WHEN_LOCKED = 0x00080000,
+ FLAG_SHOW_WALLPAPER = 0x00100000,
+ FLAG_TURN_SCREEN_ON = 0x00200000,
+ FLAG_DISMISS_KEYGUARD = 0x00400000,
+ FLAG_SPLIT_TOUCH = 0x00800000,
+ FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
+ FLAG_COMPATIBLE_WINDOW = 0x20000000,
+ FLAG_SYSTEM_ERROR = 0x40000000,
+ };
+
+ // Window types from WindowManager.LayoutParams
+ enum {
+ FIRST_APPLICATION_WINDOW = 1,
+ TYPE_BASE_APPLICATION = 1,
+ TYPE_APPLICATION = 2,
+ TYPE_APPLICATION_STARTING = 3,
+ LAST_APPLICATION_WINDOW = 99,
+ FIRST_SUB_WINDOW = 1000,
+ TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
+ TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
+ TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
+ TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
+ TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
+ LAST_SUB_WINDOW = 1999,
+ FIRST_SYSTEM_WINDOW = 2000,
+ TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
+ TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
+ TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
+ TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
+ TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
+ TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
+ TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
+ TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
+ TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
+ TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
+ TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
+ TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
+ TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
+ TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
+ TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+14,
+ TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
+ TYPE_DRAG = FIRST_SYSTEM_WINDOW+16,
+ TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+17,
+ LAST_SYSTEM_WINDOW = 2999,
+ };
+
+ sp<InputWindowHandle> inputWindowHandle;
+ sp<InputChannel> inputChannel;
+ String8 name;
+ int32_t layoutParamsFlags;
+ int32_t layoutParamsType;
+ nsecs_t dispatchingTimeout;
+ int32_t frameLeft;
+ int32_t frameTop;
+ int32_t frameRight;
+ int32_t frameBottom;
+ int32_t visibleFrameLeft;
+ int32_t visibleFrameTop;
+ int32_t visibleFrameRight;
+ int32_t visibleFrameBottom;
+ int32_t touchableAreaLeft;
+ int32_t touchableAreaTop;
+ int32_t touchableAreaRight;
+ int32_t touchableAreaBottom;
+ bool visible;
+ bool canReceiveKeys;
+ bool hasFocus;
+ bool hasWallpaper;
+ bool paused;
+ int32_t layer;
+ int32_t ownerPid;
+ int32_t ownerUid;
+
+ bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
+ bool frameContainsPoint(int32_t x, int32_t y) const;
+
+ /* Returns true if the window is of a trusted type that is allowed to silently
+ * overlay other windows for the purpose of implementing the secure views feature.
+ * Trusted overlays, such as IME windows, can partly obscure other windows without causing
+ * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
+ */
+ bool isTrustedOverlay() const;
+
+ bool supportsSplitTouch() const;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_WINDOW_H
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index b79633a..5ba1867 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -36,11 +36,11 @@
}
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel) {
+ const sp<InputWindowHandle>& inputWindowHandle) {
return 0;
}
- virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+ virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
}
virtual nsecs_t getKeyRepeatTimeout() {
@@ -61,12 +61,12 @@
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
}
- virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+ virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) {
return false;
}
- virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+ virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
return false;
}
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 9d2c52f..8ec6f53 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -368,7 +368,8 @@
return 0;
}
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
ADD_FAILURE() << "Should never be called by input reader.";
return 0;
}
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 393beda..63be030 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -532,7 +532,10 @@
for (int i = 0, count = services.size(); i < count; i++) {
Service service = services.get(i);
- service.unbind();
+ if (service.unbind()) {
+ i--;
+ count--;
+ }
}
}
@@ -575,7 +578,6 @@
Set<ComponentName> enabledServices) {
Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
- List<Service> services = mServices;
boolean isEnabled = mIsEnabled;
for (int i = 0, count = installedServices.size(); i < count; i++) {
@@ -665,23 +667,30 @@
/**
* Binds to the accessibility service.
+ *
+ * @return True if binding is successful.
*/
- public void bind() {
+ public boolean bind() {
if (mService == null) {
- mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
+ return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
}
+ return false;
}
/**
* Unbinds form the accessibility service and removes it from the data
* structures for service management.
+ *
+ * @return True if unbinding is successful.
*/
- public void unbind() {
+ public boolean unbind() {
if (mService != null) {
mContext.unbindService(this);
mComponentNameToServiceMap.remove(mComponentName);
mServices.remove(this);
+ return true;
}
+ return false;
}
/**
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index ae408fc..22dd804 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -144,6 +144,7 @@
// update the provider list.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
@@ -643,6 +644,12 @@
}
boolean addProviderLocked(ResolveInfo ri) {
+ if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+ return false;
+ }
+ if (!ri.activityInfo.isEnabled()) {
+ return false;
+ }
Provider p = parseProviderInfoXml(new ComponentName(ri.activityInfo.packageName,
ri.activityInfo.name), ri);
if (p != null) {
@@ -1160,6 +1167,7 @@
}
} else {
boolean added = false;
+ boolean changed = false;
String pkgList[] = null;
if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -1178,14 +1186,16 @@
}
pkgList = new String[] { pkgName };
added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+ changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
}
if (pkgList == null || pkgList.length == 0) {
return;
}
- if (added) {
+ if (added || changed) {
synchronized (mAppWidgetIds) {
Bundle extras = intent.getExtras();
- if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+ if (changed || (extras != null &&
+ extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
for (String pkgName : pkgList) {
// The package was just upgraded
updateProvidersForPackageLocked(pkgName);
diff --git a/services/java/com/android/server/InputApplication.java b/services/java/com/android/server/InputApplication.java
index 38420d4..ae09484 100644
--- a/services/java/com/android/server/InputApplication.java
+++ b/services/java/com/android/server/InputApplication.java
@@ -18,16 +18,19 @@
/**
* Describes input-related application properties for use by the input dispatcher.
- *
* @hide
*/
public final class InputApplication {
+ // Application handle.
+ public InputApplicationHandle inputApplicationHandle;
+
// Application name.
public String name;
-
+
// Dispatching timeout.
public long dispatchingTimeoutNanos;
-
- // The application window token.
- public Object token;
+
+ public void recycle() {
+ inputApplicationHandle = null;
+ }
}
diff --git a/services/java/com/android/server/InputApplicationHandle.java b/services/java/com/android/server/InputApplicationHandle.java
new file mode 100644
index 0000000..d396d11
--- /dev/null
+++ b/services/java/com/android/server/InputApplicationHandle.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 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;
+
+/**
+ * Functions as a handle for an application that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's
+ * application window token.
+ * @hide
+ */
+public final class InputApplicationHandle {
+ // Pointer to the native input application handle.
+ // This field is lazily initialized via JNI.
+ @SuppressWarnings("unused")
+ private int ptr;
+
+ // The window manager's application window token.
+ public final WindowManagerService.AppWindowToken appWindowToken;
+
+ private native void nativeDispose();
+
+ public InputApplicationHandle(WindowManagerService.AppWindowToken appWindowToken) {
+ this.appWindowToken = appWindowToken;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ nativeDispose();
+ super.finalize();
+ }
+}
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 410b8c2..5c2048b 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -77,7 +77,7 @@
private static native boolean nativeHasKeys(int deviceId, int sourceMask,
int[] keyCodes, boolean[] keyExists);
private static native void nativeRegisterInputChannel(InputChannel inputChannel,
- boolean monitor);
+ InputWindowHandle inputWindowHandle, boolean monitor);
private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
private static native int nativeInjectInputEvent(InputEvent event,
int injectorPid, int injectorUid, int syncMode, int timeoutMillis);
@@ -240,7 +240,7 @@
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
- nativeRegisterInputChannel(inputChannels[0], true);
+ nativeRegisterInputChannel(inputChannels[0], null, true);
inputChannels[0].dispose(); // don't need to retain the Java object reference
return inputChannels[1];
}
@@ -248,13 +248,16 @@
/**
* Registers an input channel so that it can be used as an input event target.
* @param inputChannel The input channel to register.
+ * @param inputWindowHandle The handle of the input window associated with the
+ * input channel, or null if none.
*/
- public void registerInputChannel(InputChannel inputChannel) {
+ public void registerInputChannel(InputChannel inputChannel,
+ InputWindowHandle inputWindowHandle) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
- nativeRegisterInputChannel(inputChannel, false);
+ nativeRegisterInputChannel(inputChannel, inputWindowHandle, false);
}
/**
@@ -429,13 +432,15 @@
}
@SuppressWarnings("unused")
- public void notifyInputChannelBroken(InputChannel inputChannel) {
- mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputChannel);
+ public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+ mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle);
}
@SuppressWarnings("unused")
- public long notifyANR(Object token, InputChannel inputChannel) {
- return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel);
+ public long notifyANR(InputApplicationHandle inputApplicationHandle,
+ InputWindowHandle inputWindowHandle) {
+ return mWindowManagerService.mInputMonitor.notifyANR(
+ inputApplicationHandle, inputWindowHandle);
}
@SuppressWarnings("unused")
@@ -445,14 +450,14 @@
}
@SuppressWarnings("unused")
- public boolean interceptKeyBeforeDispatching(InputChannel focus,
+ public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
KeyEvent event, int policyFlags) {
return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
focus, event, policyFlags);
}
@SuppressWarnings("unused")
- public KeyEvent dispatchUnhandledKey(InputChannel focus,
+ public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
KeyEvent event, int policyFlags) {
return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
focus, event, policyFlags);
diff --git a/services/java/com/android/server/InputWindow.java b/services/java/com/android/server/InputWindow.java
index befc770..1515290 100644
--- a/services/java/com/android/server/InputWindow.java
+++ b/services/java/com/android/server/InputWindow.java
@@ -20,64 +20,67 @@
/**
* Describes input-related window properties for use by the input dispatcher.
- *
* @hide
*/
public final class InputWindow {
+ // The window handle.
+ public InputWindowHandle inputWindowHandle;
+
// The input channel associated with the window.
public InputChannel inputChannel;
-
+
// The window name.
public String name;
-
+
// Window layout params attributes. (WindowManager.LayoutParams)
public int layoutParamsFlags;
public int layoutParamsType;
-
+
// Dispatching timeout.
public long dispatchingTimeoutNanos;
-
+
// Window frame area.
public int frameLeft;
public int frameTop;
public int frameRight;
public int frameBottom;
-
+
// Window visible frame area.
public int visibleFrameLeft;
public int visibleFrameTop;
public int visibleFrameRight;
public int visibleFrameBottom;
-
+
// Window touchable area.
public int touchableAreaLeft;
public int touchableAreaTop;
public int touchableAreaRight;
public int touchableAreaBottom;
-
+
// Window is visible.
public boolean visible;
-
+
// Window can receive keys.
public boolean canReceiveKeys;
-
+
// Window has focus.
public boolean hasFocus;
-
+
// Window has wallpaper. (window is the current wallpaper target)
public boolean hasWallpaper;
-
+
// Input event dispatching is paused.
public boolean paused;
-
+
// Window layer.
public int layer;
-
+
// Id of process and user that owns the window.
public int ownerPid;
public int ownerUid;
-
+
public void recycle() {
+ inputWindowHandle = null;
inputChannel = null;
}
}
diff --git a/services/java/com/android/server/InputWindowHandle.java b/services/java/com/android/server/InputWindowHandle.java
new file mode 100644
index 0000000..4b92939
--- /dev/null
+++ b/services/java/com/android/server/InputWindowHandle.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 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.view.WindowManagerPolicy;
+
+/**
+ * Functions as a handle for a window that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's window state.
+ * @hide
+ */
+public final class InputWindowHandle {
+ // Pointer to the native input window handle.
+ // This field is lazily initialized via JNI.
+ @SuppressWarnings("unused")
+ private int ptr;
+
+ // The input application handle.
+ public final InputApplicationHandle inputApplicationHandle;
+
+ // The window manager's window state.
+ public final WindowManagerPolicy.WindowState windowState;
+
+ private native void nativeDispose();
+
+ public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
+ WindowManagerPolicy.WindowState windowState) {
+ this.inputApplicationHandle = inputApplicationHandle;
+ this.windowState = windowState;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ nativeDispose();
+ super.finalize();
+ }
+}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 435a2a5..e323b3b 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -7926,6 +7926,14 @@
copyFrom(orig);
}
+ public void copyFrom(PackageSetting base) {
+ super.copyFrom((PackageSettingBase) base);
+
+ userId = base.userId;
+ sharedUser = base.sharedUser;
+ pkg = base.pkg;
+ }
+
@Override
public String toString() {
return "PackageSetting{"
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index c33d19d..5c823ba 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -536,7 +536,7 @@
InputChannel[] channels = InputChannel.openInputChannelPair("drag");
mServerChannel = channels[0];
mClientChannel = channels[1];
- mInputManager.registerInputChannel(mServerChannel);
+ mInputManager.registerInputChannel(mServerChannel, null);
InputQueue.registerInputChannel(mClientChannel, mDragInputHandler,
mH.getLooper().getQueue());
}
@@ -2311,7 +2311,7 @@
win.mInputChannel = inputChannels[0];
inputChannels[1].transferToBinderOutParameter(outInputChannel);
- mInputManager.registerInputChannel(win.mInputChannel);
+ mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
}
// From now on, no exceptions or errors allowed!
@@ -5711,13 +5711,13 @@
*
* Called by the InputManager.
*/
- public void notifyInputChannelBroken(InputChannel inputChannel) {
+ public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+ if (inputWindowHandle == null) {
+ return;
+ }
+
synchronized (mWindowMap) {
- WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
- if (windowState == null) {
- return; // irrelevant
- }
-
+ WindowState windowState = (WindowState) inputWindowHandle.windowState;
Slog.i(TAG, "WINDOW DIED " + windowState);
removeWindowLocked(windowState.mSession, windowState);
}
@@ -5728,11 +5728,12 @@
*
* Called by the InputManager.
*/
- public long notifyANR(Object token, InputChannel inputChannel) {
+ public long notifyANR(InputApplicationHandle inputApplicationHandle,
+ InputWindowHandle inputWindowHandle) {
AppWindowToken appWindowToken = null;
- if (inputChannel != null) {
+ if (inputWindowHandle != null) {
synchronized (mWindowMap) {
- WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
+ WindowState windowState = (WindowState) inputWindowHandle.windowState;
if (windowState != null) {
Slog.i(TAG, "Input event dispatching timed out sending to "
+ windowState.mAttrs.getTitle());
@@ -5741,8 +5742,8 @@
}
}
- if (appWindowToken == null && token != null) {
- appWindowToken = (AppWindowToken) token;
+ if (appWindowToken == null && inputApplicationHandle != null) {
+ appWindowToken = inputApplicationHandle.appWindowToken;
Slog.i(TAG, "Input event dispatching timed out sending to application "
+ appWindowToken.stringName);
}
@@ -5762,24 +5763,6 @@
}
return 0; // abort dispatching
}
-
- private WindowState getWindowStateForInputChannel(InputChannel inputChannel) {
- synchronized (mWindowMap) {
- return getWindowStateForInputChannelLocked(inputChannel);
- }
- }
-
- private WindowState getWindowStateForInputChannelLocked(InputChannel inputChannel) {
- int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- WindowState windowState = mWindows.get(i);
- if (windowState.mInputChannel == inputChannel) {
- return windowState;
- }
- }
-
- return null;
- }
private void addDragInputWindowLw(InputWindowList windowList) {
final InputWindow inputWindow = windowList.add();
@@ -5856,6 +5839,7 @@
// Add a window to our list of input windows.
final InputWindow inputWindow = mTempInputWindows.add();
+ inputWindow.inputWindowHandle = child.mInputWindowHandle;
inputWindow.inputChannel = child.mInputChannel;
inputWindow.name = child.toString();
inputWindow.layoutParamsFlags = flags;
@@ -5934,16 +5918,16 @@
/* Provides an opportunity for the window manager policy to process a key before
* ordinary dispatch. */
public boolean interceptKeyBeforeDispatching(
- InputChannel focus, KeyEvent event, int policyFlags) {
- WindowState windowState = getWindowStateForInputChannel(focus);
+ InputWindowHandle focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = (WindowState) focus.windowState;
return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
}
/* Provides an opportunity for the window manager policy to process a key that
* the application did not handle. */
public KeyEvent dispatchUnhandledKey(
- InputChannel focus, KeyEvent event, int policyFlags) {
- WindowState windowState = getWindowStateForInputChannel(focus);
+ InputWindowHandle focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = (WindowState) focus.windowState;
return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
}
@@ -5973,12 +5957,14 @@
if (newApp == null) {
mInputManager.setFocusedApplication(null);
} else {
+ mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
mTempInputApplication.name = newApp.toString();
mTempInputApplication.dispatchingTimeoutNanos =
newApp.inputDispatchingTimeoutNanos;
- mTempInputApplication.token = newApp;
-
+
mInputManager.setFocusedApplication(mTempInputApplication);
+
+ mTempInputApplication.recycle();
}
}
@@ -6823,7 +6809,8 @@
int mSurfaceLayer;
float mSurfaceAlpha;
- // Input channel
+ // Input channel and input window handle used by the input dispatcher.
+ InputWindowHandle mInputWindowHandle;
InputChannel mInputChannel;
// Used to improve performance of toString()
@@ -6915,6 +6902,8 @@
mLayer = 0;
mAnimLayer = 0;
mLastLayer = 0;
+ mInputWindowHandle = new InputWindowHandle(
+ mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
}
void attach() {
@@ -8304,11 +8293,15 @@
boolean startingMoved;
boolean firstWindowDrawn;
+ // Input application handle used by the input dispatcher.
+ InputApplicationHandle mInputApplicationHandle;
+
AppWindowToken(IApplicationToken _token) {
super(_token.asBinder(),
WindowManager.LayoutParams.TYPE_APPLICATION, true);
appWindowToken = this;
appToken = _token;
+ mInputApplicationHandle = new InputApplicationHandle(this);
}
public void setAnimation(Animation anim) {
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index ec85e54..f5a5b4d 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,7 +4,11 @@
LOCAL_SRC_FILES:= \
com_android_server_AlarmManagerService.cpp \
com_android_server_BatteryService.cpp \
+ com_android_server_InputApplication.cpp \
+ com_android_server_InputApplicationHandle.cpp \
com_android_server_InputManager.cpp \
+ com_android_server_InputWindow.cpp \
+ com_android_server_InputWindowHandle.cpp \
com_android_server_LightsService.cpp \
com_android_server_PowerManagerService.cpp \
com_android_server_SystemServer.cpp \
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
new file mode 100644
index 0000000..a46a162
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputApplication"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "com_android_server_InputApplication.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+
+ jfieldID inputApplicationHandle;
+ jfieldID name;
+ jfieldID dispatchingTimeoutNanos;
+} gInputApplicationClassInfo;
+
+
+// --- Global functions ---
+
+void android_server_InputApplication_toNative(
+ JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication) {
+ jobject inputApplicationHandleObj = env->GetObjectField(inputApplicationObj,
+ gInputApplicationClassInfo.inputApplicationHandle);
+ if (inputApplicationHandleObj) {
+ outInputApplication->inputApplicationHandle =
+ android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+ env->DeleteLocalRef(inputApplicationHandleObj);
+ } else {
+ outInputApplication->inputApplicationHandle = NULL;
+ }
+
+ jstring nameObj = jstring(env->GetObjectField(inputApplicationObj,
+ gInputApplicationClassInfo.name));
+ if (nameObj) {
+ const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+ outInputApplication->name.setTo(nameStr);
+ env->ReleaseStringUTFChars(nameObj, nameStr);
+ env->DeleteLocalRef(nameObj);
+ } else {
+ LOGE("InputApplication.name should not be null.");
+ outInputApplication->name.setTo("unknown");
+ }
+
+ outInputApplication->dispatchingTimeout = env->GetLongField(inputApplicationObj,
+ gInputApplicationClassInfo.dispatchingTimeoutNanos);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputApplication(JNIEnv* env) {
+ FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
+
+ GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
+ gInputApplicationClassInfo.clazz,
+ "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+ GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
+ "name", "Ljava/lang/String;");
+
+ GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
+ gInputApplicationClassInfo.clazz,
+ "dispatchingTimeoutNanos", "J");
+ return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplication.h b/services/jni/com_android_server_InputApplication.h
new file mode 100644
index 0000000..85fb891
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_APPLICATION_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+extern void android_server_InputApplication_toNative(
+ JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_H
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
new file mode 100644
index 0000000..ab82635
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputApplicationHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+
+ jfieldID ptr;
+} gInputApplicationHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputApplicationHandle ---
+
+NativeInputApplicationHandle::NativeInputApplicationHandle(jweak objWeak) :
+ mObjWeak(objWeak) {
+}
+
+NativeInputApplicationHandle::~NativeInputApplicationHandle() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEnv* env) {
+ return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+ JNIEnv* env, jobject inputApplicationHandleObj) {
+ if (!inputApplicationHandleObj) {
+ return NULL;
+ }
+
+ AutoMutex _l(gHandleMutex);
+
+ int ptr = env->GetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr);
+ NativeInputApplicationHandle* handle;
+ if (ptr) {
+ handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+ } else {
+ jweak objWeak = env->NewWeakGlobalRef(inputApplicationHandleObj);
+ handle = new NativeInputApplicationHandle(objWeak);
+ handle->incStrong(inputApplicationHandleObj);
+ env->SetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr,
+ reinterpret_cast<int>(handle));
+ }
+ return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputApplicationHandle_nativeDispose(JNIEnv* env, jobject obj) {
+ AutoMutex _l(gHandleMutex);
+
+ int ptr = env->GetIntField(obj, gInputApplicationHandleClassInfo.ptr);
+ if (ptr) {
+ env->SetIntField(obj, gInputApplicationHandleClassInfo.ptr, 0);
+
+ NativeInputApplicationHandle* handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+ handle->decStrong(obj);
+ }
+}
+
+
+static JNINativeMethod gInputApplicationHandleMethods[] = {
+ /* name, signature, funcPtr */
+ { "nativeDispose", "()V",
+ (void*) android_server_InputApplicationHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputApplicationHandle(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env, "com/android/server/InputApplicationHandle",
+ gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
+ LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+ FIND_CLASS(gInputApplicationHandleClassInfo.clazz, "com/android/server/InputApplicationHandle");
+
+ GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, gInputApplicationHandleClassInfo.clazz,
+ "ptr", "I");
+
+ return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h
new file mode 100644
index 0000000..9d18721
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputApplicationHandle : public InputApplicationHandle {
+public:
+ NativeInputApplicationHandle(jweak objWeak);
+ virtual ~NativeInputApplicationHandle();
+
+ jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
+
+private:
+ jweak mObjWeak;
+};
+
+
+extern sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+ JNIEnv* env, jobject inputApplicationHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 5ed63f0..e04e4c3 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -42,11 +42,13 @@
#include <android/graphics/GraphicsJNI.h>
#include "com_android_server_PowerManagerService.h"
+#include "com_android_server_InputApplication.h"
+#include "com_android_server_InputApplicationHandle.h"
+#include "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
namespace android {
-// ----------------------------------------------------------------------------
-
static struct {
jclass clazz;
@@ -68,44 +70,6 @@
static struct {
jclass clazz;
-
- jfieldID inputChannel;
- jfieldID name;
- jfieldID layoutParamsFlags;
- jfieldID layoutParamsType;
- jfieldID dispatchingTimeoutNanos;
- jfieldID frameLeft;
- jfieldID frameTop;
- jfieldID frameRight;
- jfieldID frameBottom;
- jfieldID visibleFrameLeft;
- jfieldID visibleFrameTop;
- jfieldID visibleFrameRight;
- jfieldID visibleFrameBottom;
- jfieldID touchableAreaLeft;
- jfieldID touchableAreaTop;
- jfieldID touchableAreaRight;
- jfieldID touchableAreaBottom;
- jfieldID visible;
- jfieldID canReceiveKeys;
- jfieldID hasFocus;
- jfieldID hasWallpaper;
- jfieldID paused;
- jfieldID layer;
- jfieldID ownerPid;
- jfieldID ownerUid;
-} gInputWindowClassInfo;
-
-static struct {
- jclass clazz;
-
- jfieldID name;
- jfieldID dispatchingTimeoutNanos;
- jfieldID token;
-} gInputApplicationClassInfo;
-
-static struct {
- jclass clazz;
} gKeyEventClassInfo;
static struct {
@@ -141,7 +105,29 @@
jfieldID hotSpotY;
} gPointerIconClassInfo;
-// ----------------------------------------------------------------------------
+
+// --- Global functions ---
+
+static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
+ const sp<InputApplicationHandle>& inputApplicationHandle) {
+ if (inputApplicationHandle == NULL) {
+ return NULL;
+ }
+ return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())->
+ getInputApplicationHandleObjLocalRef(env);
+}
+
+static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
+ const sp<InputWindowHandle>& inputWindowHandle) {
+ if (inputWindowHandle == NULL) {
+ return NULL;
+ }
+ return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
+ getInputWindowHandleObjLocalRef(env);
+}
+
+
+// --- NativeInputManager ---
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
@@ -160,7 +146,7 @@
void setDisplayOrientation(int32_t displayId, int32_t orientation);
status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
- jweak inputChannelObjWeak, bool monitor);
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
@@ -182,37 +168,22 @@
uint32_t policyFlags);
virtual void notifyConfigurationChanged(nsecs_t when);
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel);
- virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
+ const sp<InputWindowHandle>& inputWindowHandle);
+ virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
virtual nsecs_t getKeyRepeatTimeout();
virtual nsecs_t getKeyRepeatDelay();
virtual int32_t getMaxEventsPerSecond();
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
- virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+ virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags);
- virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+ virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
virtual bool checkInjectEventsPermissionNonReentrant(
int32_t injectorPid, int32_t injectorUid);
private:
- class ApplicationToken : public InputApplicationHandle {
- jweak mTokenObjWeak;
-
- public:
- ApplicationToken(jweak tokenObjWeak) :
- mTokenObjWeak(tokenObjWeak) { }
-
- virtual ~ApplicationToken() {
- JNIEnv* env = NativeInputManager::jniEnv();
- env->DeleteWeakGlobalRef(mTokenObjWeak);
- }
-
- inline jweak getTokenObj() { return mTokenObjWeak; }
- };
-
sp<InputManager> mInputManager;
jobject mCallbacksObj;
@@ -232,19 +203,12 @@
// Pointer controller singleton, created and destroyed as needed.
wp<PointerController> pointerController;
-
- // Weak references to all currently registered input channels by connection pointer.
- KeyedVector<InputChannel*, jweak> inputChannelObjWeakTable;
} mLocked;
// Power manager interactions.
bool isScreenOn();
bool isScreenBright();
- jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
-
- static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
-
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
static inline JNIEnv* jniEnv() {
@@ -252,7 +216,7 @@
}
};
-// ----------------------------------------------------------------------------
+
NativeInputManager::NativeInputManager(jobject callbacksObj) :
mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
@@ -328,88 +292,17 @@
}
status_t NativeInputManager::registerInputChannel(JNIEnv* env,
- const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
- jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
- if (! inputChannelObjWeak) {
- LOGE("Could not create weak reference for input channel.");
- LOGE_EX(env);
- return NO_MEMORY;
- }
-
- status_t status;
- {
- AutoMutex _l(mLock);
-
- ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
- if (index >= 0) {
- LOGE("Input channel object '%s' has already been registered",
- inputChannel->getName().string());
- status = INVALID_OPERATION;
- goto DeleteWeakRef;
- }
-
- mLocked.inputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
- }
-
- status = mInputManager->getDispatcher()->registerInputChannel(inputChannel, monitor);
- if (! status) {
- // Success.
- return OK;
- }
-
- // Failed!
- {
- AutoMutex _l(mLock);
- mLocked.inputChannelObjWeakTable.removeItem(inputChannel.get());
- }
-
-DeleteWeakRef:
- env->DeleteWeakGlobalRef(inputChannelObjWeak);
- return status;
+ const sp<InputChannel>& inputChannel,
+ const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+ return mInputManager->getDispatcher()->registerInputChannel(
+ inputChannel, inputWindowHandle, monitor);
}
status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
const sp<InputChannel>& inputChannel) {
- jweak inputChannelObjWeak;
- {
- AutoMutex _l(mLock);
-
- ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannel.get());
- if (index < 0) {
- LOGE("Input channel object '%s' is not currently registered",
- inputChannel->getName().string());
- return INVALID_OPERATION;
- }
-
- inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
- mLocked.inputChannelObjWeakTable.removeItemsAt(index);
- }
-
- env->DeleteWeakGlobalRef(inputChannelObjWeak);
-
return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
}
-jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
- const sp<InputChannel>& inputChannel) {
- InputChannel* inputChannelPtr = inputChannel.get();
- if (! inputChannelPtr) {
- return NULL;
- }
-
- {
- AutoMutex _l(mLock);
-
- ssize_t index = mLocked.inputChannelObjWeakTable.indexOfKey(inputChannelPtr);
- if (index < 0) {
- return NULL;
- }
-
- jweak inputChannelObjWeak = mLocked.inputChannelObjWeakTable.valueAt(index);
- return env->NewLocalRef(inputChannelObjWeak);
- }
-}
-
bool NativeInputManager::getDisplayInfo(int32_t displayId,
int32_t* width, int32_t* height, int32_t* orientation) {
bool result = false;
@@ -549,50 +442,46 @@
}
nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputChannel>& inputChannel) {
+ const sp<InputWindowHandle>& inputWindowHandle) {
#if DEBUG_INPUT_DISPATCHER_POLICY
LOGD("notifyANR");
#endif
JNIEnv* env = jniEnv();
- jobject tokenObjLocal;
- if (inputApplicationHandle.get()) {
- ApplicationToken* token = static_cast<ApplicationToken*>(inputApplicationHandle.get());
- jweak tokenObjWeak = token->getTokenObj();
- tokenObjLocal = env->NewLocalRef(tokenObjWeak);
- } else {
- tokenObjLocal = NULL;
- }
+ jobject inputApplicationHandleObj =
+ getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
+ jobject inputWindowHandleObj =
+ getInputWindowHandleObjLocalRef(env, inputWindowHandle);
- jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
jlong newTimeout = env->CallLongMethod(mCallbacksObj,
- gCallbacksClassInfo.notifyANR, tokenObjLocal, inputChannelObjLocal);
+ gCallbacksClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
newTimeout = 0; // abort dispatch
} else {
assert(newTimeout >= 0);
}
- env->DeleteLocalRef(tokenObjLocal);
- env->DeleteLocalRef(inputChannelObjLocal);
+ env->DeleteLocalRef(inputWindowHandleObj);
+ env->DeleteLocalRef(inputApplicationHandleObj);
return newTimeout;
}
-void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
#if DEBUG_INPUT_DISPATCHER_POLICY
- LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
+ LOGD("notifyInputChannelBroken");
#endif
JNIEnv* env = jniEnv();
- jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
- if (inputChannelObjLocal) {
+ jobject inputWindowHandleObj =
+ getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+ if (inputWindowHandleObj) {
env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
- inputChannelObjLocal);
+ inputWindowHandleObj);
checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
- env->DeleteLocalRef(inputChannelObjLocal);
+ env->DeleteLocalRef(inputWindowHandleObj);
}
}
@@ -630,160 +519,32 @@
jsize length = env->GetArrayLength(windowObjArray);
for (jsize i = 0; i < length; i++) {
- jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
- if (! inputTargetObj) {
+ jobject windowObj = env->GetObjectArrayElement(windowObjArray, i);
+ if (! windowObj) {
break; // found null element indicating end of used portion of the array
}
windows.push();
InputWindow& window = windows.editTop();
- bool valid = populateWindow(env, inputTargetObj, window);
- if (! valid) {
+ android_server_InputWindow_toNative(env, windowObj, &window);
+ if (window.inputChannel == NULL) {
windows.pop();
}
-
- env->DeleteLocalRef(inputTargetObj);
+ env->DeleteLocalRef(windowObj);
}
mInputManager->getDispatcher()->setInputWindows(windows);
}
-bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
- InputWindow& outWindow) {
- bool valid = false;
-
- jobject inputChannelObj = env->GetObjectField(windowObj,
- gInputWindowClassInfo.inputChannel);
- if (inputChannelObj) {
- sp<InputChannel> inputChannel =
- android_view_InputChannel_getInputChannel(env, inputChannelObj);
- if (inputChannel != NULL) {
- jstring name = jstring(env->GetObjectField(windowObj,
- gInputWindowClassInfo.name));
- jint layoutParamsFlags = env->GetIntField(windowObj,
- gInputWindowClassInfo.layoutParamsFlags);
- jint layoutParamsType = env->GetIntField(windowObj,
- gInputWindowClassInfo.layoutParamsType);
- jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
- gInputWindowClassInfo.dispatchingTimeoutNanos);
- jint frameLeft = env->GetIntField(windowObj,
- gInputWindowClassInfo.frameLeft);
- jint frameTop = env->GetIntField(windowObj,
- gInputWindowClassInfo.frameTop);
- jint frameRight = env->GetIntField(windowObj,
- gInputWindowClassInfo.frameRight);
- jint frameBottom = env->GetIntField(windowObj,
- gInputWindowClassInfo.frameBottom);
- jint visibleFrameLeft = env->GetIntField(windowObj,
- gInputWindowClassInfo.visibleFrameLeft);
- jint visibleFrameTop = env->GetIntField(windowObj,
- gInputWindowClassInfo.visibleFrameTop);
- jint visibleFrameRight = env->GetIntField(windowObj,
- gInputWindowClassInfo.visibleFrameRight);
- jint visibleFrameBottom = env->GetIntField(windowObj,
- gInputWindowClassInfo.visibleFrameBottom);
- jint touchableAreaLeft = env->GetIntField(windowObj,
- gInputWindowClassInfo.touchableAreaLeft);
- jint touchableAreaTop = env->GetIntField(windowObj,
- gInputWindowClassInfo.touchableAreaTop);
- jint touchableAreaRight = env->GetIntField(windowObj,
- gInputWindowClassInfo.touchableAreaRight);
- jint touchableAreaBottom = env->GetIntField(windowObj,
- gInputWindowClassInfo.touchableAreaBottom);
- jboolean visible = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.visible);
- jboolean canReceiveKeys = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.canReceiveKeys);
- jboolean hasFocus = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.hasFocus);
- jboolean hasWallpaper = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.hasWallpaper);
- jboolean paused = env->GetBooleanField(windowObj,
- gInputWindowClassInfo.paused);
- jint layer = env->GetIntField(windowObj,
- gInputWindowClassInfo.layer);
- jint ownerPid = env->GetIntField(windowObj,
- gInputWindowClassInfo.ownerPid);
- jint ownerUid = env->GetIntField(windowObj,
- gInputWindowClassInfo.ownerUid);
-
- const char* nameStr = env->GetStringUTFChars(name, NULL);
-
- outWindow.inputChannel = inputChannel;
- outWindow.name.setTo(nameStr);
- outWindow.layoutParamsFlags = layoutParamsFlags;
- outWindow.layoutParamsType = layoutParamsType;
- outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
- outWindow.frameLeft = frameLeft;
- outWindow.frameTop = frameTop;
- outWindow.frameRight = frameRight;
- outWindow.frameBottom = frameBottom;
- outWindow.visibleFrameLeft = visibleFrameLeft;
- outWindow.visibleFrameTop = visibleFrameTop;
- outWindow.visibleFrameRight = visibleFrameRight;
- outWindow.visibleFrameBottom = visibleFrameBottom;
- outWindow.touchableAreaLeft = touchableAreaLeft;
- outWindow.touchableAreaTop = touchableAreaTop;
- outWindow.touchableAreaRight = touchableAreaRight;
- outWindow.touchableAreaBottom = touchableAreaBottom;
- outWindow.visible = visible;
- outWindow.canReceiveKeys = canReceiveKeys;
- outWindow.hasFocus = hasFocus;
- outWindow.hasWallpaper = hasWallpaper;
- outWindow.paused = paused;
- outWindow.layer = layer;
- outWindow.ownerPid = ownerPid;
- outWindow.ownerUid = ownerUid;
-
- env->ReleaseStringUTFChars(name, nameStr);
- env->DeleteLocalRef(name);
- valid = true;
- } else {
- LOGW("Dropping input target because its input channel is not initialized.");
- }
-
- env->DeleteLocalRef(inputChannelObj);
- } else {
- LOGW("Dropping input target because the input channel object was null.");
- }
- return valid;
-}
-
void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
if (applicationObj) {
- jstring nameObj = jstring(env->GetObjectField(applicationObj,
- gInputApplicationClassInfo.name));
- jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
- gInputApplicationClassInfo.dispatchingTimeoutNanos);
- jobject tokenObj = env->GetObjectField(applicationObj,
- gInputApplicationClassInfo.token);
- jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
- if (! tokenObjWeak) {
- LOGE("Could not create weak reference for application token.");
- LOGE_EX(env);
- env->ExceptionClear();
- }
- env->DeleteLocalRef(tokenObj);
-
- String8 name;
- if (nameObj) {
- const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
- name.setTo(nameStr);
- env->ReleaseStringUTFChars(nameObj, nameStr);
- env->DeleteLocalRef(nameObj);
- } else {
- LOGE("InputApplication.name should not be null.");
- name.setTo("unknown");
- }
-
InputApplication application;
- application.name = name;
- application.dispatchingTimeout = dispatchingTimeoutNanos;
- application.handle = new ApplicationToken(tokenObjWeak);
- mInputManager->getDispatcher()->setFocusedApplication(& application);
- } else {
- mInputManager->getDispatcher()->setFocusedApplication(NULL);
+ android_server_InputApplication_toNative(env, applicationObj, &application);
+ if (application.inputApplicationHandle != NULL) {
+ mInputManager->getDispatcher()->setFocusedApplication(&application);
+ }
}
+ mInputManager->getDispatcher()->setFocusedApplication(NULL);
}
void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
@@ -875,7 +636,8 @@
}
}
-bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::interceptKeyBeforeDispatching(
+ const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) {
// Policy:
// - Ignore untrusted events and pass them along.
@@ -885,13 +647,13 @@
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
- // Note: inputChannel may be null.
- jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+ // Note: inputWindowHandle may be null.
+ jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
gCallbacksClassInfo.interceptKeyBeforeDispatching,
- inputChannelObj, keyEventObj, policyFlags);
+ inputWindowHandleObj, keyEventObj, policyFlags);
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
@@ -899,12 +661,12 @@
} else {
LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
}
- env->DeleteLocalRef(inputChannelObj);
+ env->DeleteLocalRef(inputWindowHandleObj);
}
return result;
}
-bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
// Policy:
// - Ignore untrusted events and do not perform default handling.
@@ -912,13 +674,13 @@
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
- // Note: inputChannel may be null.
- jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+ // Note: inputWindowHandle may be null.
+ jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
gCallbacksClassInfo.dispatchUnhandledKey,
- inputChannelObj, keyEventObj, policyFlags);
+ inputWindowHandleObj, keyEventObj, policyFlags);
checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
@@ -935,7 +697,7 @@
} else {
LOGE("Failed to obtain key event object for dispatchUnhandledKey.");
}
- env->DeleteLocalRef(inputChannelObj);
+ env->DeleteLocalRef(inputWindowHandleObj);
}
return result;
}
@@ -1079,7 +841,7 @@
}
static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
- jobject inputChannelObj, jboolean monitor) {
+ jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
if (checkInputManagerUnitialized(env)) {
return;
}
@@ -1091,9 +853,11 @@
return;
}
+ sp<InputWindowHandle> inputWindowHandle =
+ android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
status_t status = gNativeInputManager->registerInputChannel(
- env, inputChannel, inputChannelObj, monitor);
+ env, inputChannel, inputWindowHandle, monitor);
if (status) {
jniThrowRuntimeException(env, "Failed to register input channel. "
"Check logs for details.");
@@ -1311,7 +1075,8 @@
(void*) android_server_InputManager_nativeGetSwitchState },
{ "nativeHasKeys", "(II[I[Z)Z",
(void*) android_server_InputManager_nativeHasKeys },
- { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
+ { "nativeRegisterInputChannel",
+ "(Landroid/view/InputChannel;Lcom/android/server/InputWindowHandle;Z)V",
(void*) android_server_InputManager_nativeRegisterInputChannel },
{ "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
(void*) android_server_InputManager_nativeUnregisterInputChannel },
@@ -1364,21 +1129,22 @@
"notifyLidSwitchChanged", "(JZ)V");
GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
- "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
+ "notifyInputChannelBroken", "(Lcom/android/server/InputWindowHandle;)V");
GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
- "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
+ "notifyANR",
+ "(Lcom/android/server/InputApplicationHandle;Lcom/android/server/InputWindowHandle;)J");
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
"interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
"interceptKeyBeforeDispatching",
- "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
+ "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz,
"dispatchUnhandledKey",
- "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
+ "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
"checkInjectEventsPermission", "(II)Z");
@@ -1401,99 +1167,6 @@
GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, gCallbacksClassInfo.clazz,
"getPointerIcon", "()Lcom/android/server/InputManager$PointerIcon;");
- // InputWindow
-
- FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
-
- GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
- "inputChannel", "Landroid/view/InputChannel;");
-
- GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
- "name", "Ljava/lang/String;");
-
- GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
- "layoutParamsFlags", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
- "layoutParamsType", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
- "dispatchingTimeoutNanos", "J");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
- "frameLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
- "frameTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
- "frameRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
- "frameBottom", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
- "visibleFrameLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
- "visibleFrameTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
- "visibleFrameRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
- "visibleFrameBottom", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
- "touchableAreaLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
- "touchableAreaTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
- "touchableAreaRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
- "touchableAreaBottom", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
- "visible", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
- "canReceiveKeys", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
- "hasFocus", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
- "hasWallpaper", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
- "paused", "Z");
-
- GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
- "layer", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
- "ownerPid", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
- "ownerUid", "I");
-
- // InputApplication
-
- FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
-
- GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
- "name", "Ljava/lang/String;");
-
- GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
- gInputApplicationClassInfo.clazz,
- "dispatchingTimeoutNanos", "J");
-
- GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
- "token", "Ljava/lang/Object;");
-
// KeyEvent
FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
new file mode 100644
index 0000000..a4609a0
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindow"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <android_view_InputChannel.h>
+#include "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+
+ jfieldID inputWindowHandle;
+ jfieldID inputChannel;
+ jfieldID name;
+ jfieldID layoutParamsFlags;
+ jfieldID layoutParamsType;
+ jfieldID dispatchingTimeoutNanos;
+ jfieldID frameLeft;
+ jfieldID frameTop;
+ jfieldID frameRight;
+ jfieldID frameBottom;
+ jfieldID visibleFrameLeft;
+ jfieldID visibleFrameTop;
+ jfieldID visibleFrameRight;
+ jfieldID visibleFrameBottom;
+ jfieldID touchableAreaLeft;
+ jfieldID touchableAreaTop;
+ jfieldID touchableAreaRight;
+ jfieldID touchableAreaBottom;
+ jfieldID visible;
+ jfieldID canReceiveKeys;
+ jfieldID hasFocus;
+ jfieldID hasWallpaper;
+ jfieldID paused;
+ jfieldID layer;
+ jfieldID ownerPid;
+ jfieldID ownerUid;
+} gInputWindowClassInfo;
+
+
+// --- Global functions ---
+
+void android_server_InputWindow_toNative(
+ JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow) {
+ jobject inputWindowHandleObj = env->GetObjectField(inputWindowObj,
+ gInputWindowClassInfo.inputWindowHandle);
+ if (inputWindowHandleObj) {
+ outInputWindow->inputWindowHandle =
+ android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
+ env->DeleteLocalRef(inputWindowHandleObj);
+ } else {
+ outInputWindow->inputWindowHandle = NULL;
+ }
+
+ jobject inputChannelObj = env->GetObjectField(inputWindowObj,
+ gInputWindowClassInfo.inputChannel);
+ if (inputChannelObj) {
+ outInputWindow->inputChannel =
+ android_view_InputChannel_getInputChannel(env, inputChannelObj);
+ env->DeleteLocalRef(inputChannelObj);
+ } else {
+ outInputWindow->inputChannel = NULL;
+ }
+
+ jstring nameObj = jstring(env->GetObjectField(inputWindowObj,
+ gInputWindowClassInfo.name));
+ if (nameObj) {
+ const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+ outInputWindow->name.setTo(nameStr);
+ env->ReleaseStringUTFChars(nameObj, nameStr);
+ env->DeleteLocalRef(nameObj);
+ } else {
+ LOGE("InputWindow.name should not be null.");
+ outInputWindow->name.setTo("unknown");
+ }
+
+ outInputWindow->layoutParamsFlags = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.layoutParamsFlags);
+ outInputWindow->layoutParamsType = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.layoutParamsType);
+ outInputWindow->dispatchingTimeout = env->GetLongField(inputWindowObj,
+ gInputWindowClassInfo.dispatchingTimeoutNanos);
+ outInputWindow->frameLeft = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.frameLeft);
+ outInputWindow->frameTop = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.frameTop);
+ outInputWindow->frameRight = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.frameRight);
+ outInputWindow->frameBottom = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.frameBottom);
+ outInputWindow->visibleFrameLeft = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.visibleFrameLeft);
+ outInputWindow->visibleFrameTop = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.visibleFrameTop);
+ outInputWindow->visibleFrameRight = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.visibleFrameRight);
+ outInputWindow->visibleFrameBottom = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.visibleFrameBottom);
+ outInputWindow->touchableAreaLeft = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.touchableAreaLeft);
+ outInputWindow->touchableAreaTop = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.touchableAreaTop);
+ outInputWindow->touchableAreaRight = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.touchableAreaRight);
+ outInputWindow->touchableAreaBottom = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.touchableAreaBottom);
+ outInputWindow->visible = env->GetBooleanField(inputWindowObj,
+ gInputWindowClassInfo.visible);
+ outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj,
+ gInputWindowClassInfo.canReceiveKeys);
+ outInputWindow->hasFocus = env->GetBooleanField(inputWindowObj,
+ gInputWindowClassInfo.hasFocus);
+ outInputWindow->hasWallpaper = env->GetBooleanField(inputWindowObj,
+ gInputWindowClassInfo.hasWallpaper);
+ outInputWindow->paused = env->GetBooleanField(inputWindowObj,
+ gInputWindowClassInfo.paused);
+ outInputWindow->layer = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.layer);
+ outInputWindow->ownerPid = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.ownerPid);
+ outInputWindow->ownerUid = env->GetIntField(inputWindowObj,
+ gInputWindowClassInfo.ownerUid);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputWindow(JNIEnv* env) {
+ FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
+
+ GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, gInputWindowClassInfo.clazz,
+ "inputWindowHandle", "Lcom/android/server/InputWindowHandle;");
+
+ GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
+ "inputChannel", "Landroid/view/InputChannel;");
+
+ GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
+ "name", "Ljava/lang/String;");
+
+ GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
+ "layoutParamsFlags", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
+ "layoutParamsType", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
+ "dispatchingTimeoutNanos", "J");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
+ "frameLeft", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
+ "frameTop", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
+ "frameRight", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
+ "frameBottom", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
+ "visibleFrameLeft", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
+ "visibleFrameTop", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
+ "visibleFrameRight", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
+ "visibleFrameBottom", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
+ "touchableAreaLeft", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
+ "touchableAreaTop", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
+ "touchableAreaRight", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
+ "touchableAreaBottom", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
+ "visible", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
+ "canReceiveKeys", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
+ "hasFocus", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
+ "hasWallpaper", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
+ "paused", "Z");
+
+ GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
+ "layer", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
+ "ownerPid", "I");
+
+ GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
+ "ownerUid", "I");
+ return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindow.h b/services/jni/com_android_server_InputWindow.h
new file mode 100644
index 0000000..eaf7bde
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
+#define _ANDROID_SERVER_INPUT_WINDOW_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+extern void android_server_InputWindow_toNative(
+ JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_H
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
new file mode 100644
index 0000000..4d66212
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindowHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputWindowHandle.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+
+ jfieldID ptr;
+ jfieldID inputApplicationHandle;
+} gInputWindowHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputWindowHandle ---
+
+NativeInputWindowHandle::NativeInputWindowHandle(
+ const sp<InputApplicationHandle>& inputApplicationHandle, jweak objWeak) :
+ InputWindowHandle(inputApplicationHandle),
+ mObjWeak(objWeak) {
+}
+
+NativeInputWindowHandle::~NativeInputWindowHandle() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
+ return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+ JNIEnv* env, jobject inputWindowHandleObj) {
+ if (!inputWindowHandleObj) {
+ return NULL;
+ }
+
+ AutoMutex _l(gHandleMutex);
+
+ int ptr = env->GetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr);
+ NativeInputWindowHandle* handle;
+ if (ptr) {
+ handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+ } else {
+ jobject inputApplicationHandleObj = env->GetObjectField(inputWindowHandleObj,
+ gInputWindowHandleClassInfo.inputApplicationHandle);
+ sp<InputApplicationHandle> inputApplicationHandle =
+ android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+ env->DeleteLocalRef(inputApplicationHandleObj);
+
+ jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj);
+ handle = new NativeInputWindowHandle(inputApplicationHandle, objWeak);
+ handle->incStrong(inputWindowHandleObj);
+ env->SetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr,
+ reinterpret_cast<int>(handle));
+ }
+ return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputWindowHandle_nativeDispose(JNIEnv* env, jobject obj) {
+ AutoMutex _l(gHandleMutex);
+
+ int ptr = env->GetIntField(obj, gInputWindowHandleClassInfo.ptr);
+ if (ptr) {
+ env->SetIntField(obj, gInputWindowHandleClassInfo.ptr, 0);
+
+ NativeInputWindowHandle* handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+ handle->decStrong(obj);
+ }
+}
+
+
+static JNINativeMethod gInputWindowHandleMethods[] = {
+ /* name, signature, funcPtr */
+ { "nativeDispose", "()V",
+ (void*) android_server_InputWindowHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputWindowHandle(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env, "com/android/server/InputWindowHandle",
+ gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
+ LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+ FIND_CLASS(gInputWindowHandleClassInfo.clazz, "com/android/server/InputWindowHandle");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, gInputWindowHandleClassInfo.clazz,
+ "ptr", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
+ gInputWindowHandleClassInfo.clazz,
+ "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+ return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h
new file mode 100644
index 0000000..43f2a6b
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+#define _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputWindowHandle : public InputWindowHandle {
+public:
+ NativeInputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+ jweak objWeak);
+ virtual ~NativeInputWindowHandle();
+
+ jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
+
+private:
+ jweak mObjWeak;
+};
+
+
+extern sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+ JNIEnv* env, jobject inputWindowHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index cd4f0a4..bdd6d80 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -6,6 +6,10 @@
namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_BatteryService(JNIEnv* env);
+int register_android_server_InputApplication(JNIEnv* env);
+int register_android_server_InputApplicationHandle(JNIEnv* env);
+int register_android_server_InputWindow(JNIEnv* env);
+int register_android_server_InputWindowHandle(JNIEnv* env);
int register_android_server_InputManager(JNIEnv* env);
int register_android_server_LightsService(JNIEnv* env);
int register_android_server_PowerManagerService(JNIEnv* env);
@@ -28,6 +32,10 @@
LOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_PowerManagerService(env);
+ register_android_server_InputApplication(env);
+ register_android_server_InputApplicationHandle(env);
+ register_android_server_InputWindow(env);
+ register_android_server_InputWindowHandle(env);
register_android_server_InputManager(env);
register_android_server_LightsService(env);
register_android_server_AlarmManagerService(env);
diff --git a/tests/CoreTests/android/core/HeapTest.java b/tests/CoreTests/android/core/HeapTest.java
index 6116f5e..98cb28a 100644
--- a/tests/CoreTests/android/core/HeapTest.java
+++ b/tests/CoreTests/android/core/HeapTest.java
@@ -540,94 +540,4 @@
objSize = (objSize * 4) / 5;
}
}
-
- // TODO: flaky test
- //@SmallTest
- public void testExternalOomeLarge() {
- /* Just shy of the typical max heap size so that it will actually
- * try to allocate it instead of short-circuiting.
- */
- final int HUGE_SIZE = (16 * 1024 * 1024 - 32);
-
- assertFalse(VMRuntime.getRuntime().trackExternalAllocation(HUGE_SIZE));
- }
-
- /**
- * "Allocates" external memory in progressively smaller chunks until there's
- * only roughly 16 bytes left.
- *
- * @return the number of bytes allocated
- */
- private long allocateMaxExternal() {
- final VMRuntime runtime = VMRuntime.getRuntime();
- final int SIXTEEN_MB = (16 * 1024 * 1024);
- final int MIN_SIZE = 16;
- long totalAllocated = 0;
- boolean success;
-
- success = false;
- try {
- /* "Allocate" progressively smaller chunks to "fill up" the entire heap.
- */
- int objSize = 1 * 1024 * 1024;
- while (objSize >= MIN_SIZE) {
- boolean sawFailure = false;
- for (int i = 0; i < SIXTEEN_MB / objSize; i++) {
- if (runtime.trackExternalAllocation(objSize)) {
- totalAllocated += objSize;
- } else {
- sawFailure = true;
- break;
- }
- }
-
- if (!sawFailure) {
- throw new RuntimeException("Test failed: " +
- "no failure while filling heap");
- }
-
- objSize = (objSize * 4) / 5;
- }
- success = true;
- } finally {
- if (!success) {
- runtime.trackExternalFree(totalAllocated);
- totalAllocated = 0;
- }
- }
- return totalAllocated;
- }
-
- public void xxtest00ExternalOomeSmall() {
- VMRuntime.getRuntime().trackExternalFree(allocateMaxExternal());
- }
-
- /**
- * Allocates as much external memory as possible, then allocates from the heap
- * until an OOME is caught.
- *
- * It's nice to run this test while the real heap is small, hence the '00' in its
- * name to force it to run before testOomeSmall().
- */
- public void xxtest00CombinedOomeSmall() {
- long totalAllocated = 0;
- boolean sawEx = false;
- try {
- totalAllocated = allocateMaxExternal();
- LinkedList<Object> list = new LinkedList<Object>();
- try {
- while (true) {
- list.add((Object)new byte[8192]);
- }
- /*NOTREACHED*/
- } catch (OutOfMemoryError oom) {
- sawEx = true;
- }
- } finally {
- VMRuntime.getRuntime().trackExternalFree(totalAllocated);
- }
- assertTrue(sawEx);
- }
-
- //TODO: test external alloc debugging/inspection
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
index 91e3b84..8ca842e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
@@ -23,6 +23,7 @@
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.View;
@@ -31,7 +32,9 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().setBackgroundDrawable(new ColorDrawable(0xffffffff));
final LinesView view = new LinesView(this);
+ //view.setAlpha(0.80f);
setContentView(view);
}
@@ -91,8 +94,6 @@
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
- canvas.drawARGB(255, 255, 255, 255);
-
canvas.save();
canvas.translate(100.0f, 20.0f);
diff --git a/tests/StatusBar/AndroidManifest.xml b/tests/StatusBar/AndroidManifest.xml
index ddb756b..81442bf 100644
--- a/tests/StatusBar/AndroidManifest.xml
+++ b/tests/StatusBar/AndroidManifest.xml
@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.STATUS_BAR" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.VIBRATE" />
+ <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<application>
<activity android:name="StatusBarTest" android:label="_StatusBar">
diff --git a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
index 92d5bee..31a1cf5a 100644
--- a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
@@ -26,6 +26,8 @@
import android.os.IPowerManager;
import android.widget.ListView;
import android.content.Intent;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.StatusBarManager;
@@ -66,6 +68,24 @@
return mTests;
}
private Test[] mTests = new Test[] {
+ new Test("Enable settings widget") {
+ public void run() {
+ PackageManager pm = getPackageManager();
+ pm.setComponentEnabledSetting(new ComponentName("com.android.settings",
+ "com.android.settings.widget.SettingsAppWidgetProvider"),
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+
+ }
+ },
+ new Test("Disable settings widget") {
+ public void run() {
+ PackageManager pm = getPackageManager();
+ pm.setComponentEnabledSetting(new ComponentName("com.android.settings",
+ "com.android.settings.widget.SettingsAppWidgetProvider"),
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
+
+ }
+ },
new Test("Enable proximity") {
public void run() {
mProx.acquire();
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index c57aef6..096498b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -351,7 +351,8 @@
If the exception happened on open, bm will be null.
If it happened on close, bm is still valid.
*/
- Bridge.getLog().error(null, e);
+ Bridge.getLog().error(null,
+ String.format("Error decoding bitmap of id 0x%x", id), e);
} finally {
try {
if (is != null) is.close();
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index e9fb30a..5524f4f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -73,7 +73,7 @@
oos = new ObjectOutputStream(baos);
oos.writeObject(chunk);
} catch (IOException e) {
- Bridge.getLog().error("Failed to serialize NinePatchChunk.", e);
+ Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e);
return null;
} finally {
if (oos != null) {
@@ -196,10 +196,10 @@
sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
}
} catch (IOException e) {
- Bridge.getLog().error("Failed to deserialize NinePatchChunk content.", e);
+ Bridge.getLog().error(null, "Failed to deserialize NinePatchChunk content.", e);
return null;
} catch (ClassNotFoundException e) {
- Bridge.getLog().error("Failed to deserialize NinePatchChunk class.", e);
+ Bridge.getLog().error(null, "Failed to deserialize NinePatchChunk class.", e);
return null;
} finally {
if (ois != null) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index bc13b52..33c2aed 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -135,6 +135,123 @@
// ---- native methods ----
+ /*package*/ static boolean isEmpty(Region thisRegion) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return true;
+ }
+
+ return regionDelegate.mArea.isEmpty();
+ }
+
+ /*package*/ static boolean isRect(Region thisRegion) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return true;
+ }
+
+ return regionDelegate.mArea.isRectangular();
+ }
+
+ /*package*/ static boolean isComplex(Region thisRegion) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return true;
+ }
+
+ return regionDelegate.mArea.isSingular() == false;
+ }
+
+ /*package*/ static boolean contains(Region thisRegion, int x, int y) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return false;
+ }
+
+ return regionDelegate.mArea.contains(x, y);
+ }
+
+ /*package*/ static boolean quickContains(Region thisRegion,
+ int left, int top, int right, int bottom) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return false;
+ }
+
+ return regionDelegate.mArea.isRectangular() &&
+ regionDelegate.mArea.contains(left, top, right - left, bottom - top);
+ }
+
+ /*package*/ static boolean quickReject(Region thisRegion,
+ int left, int top, int right, int bottom) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return false;
+ }
+
+ return regionDelegate.mArea.isEmpty() ||
+ regionDelegate.mArea.intersects(left, top, right - left, bottom - top) == false;
+ }
+
+ /*package*/ static boolean quickReject(Region thisRegion, Region rgn) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return false;
+ }
+
+ Region_Delegate targetRegionDelegate = sManager.getDelegate(rgn.mNativeRegion);
+ if (targetRegionDelegate == null) {
+ return false;
+ }
+
+ return regionDelegate.mArea.isEmpty() ||
+ regionDelegate.mArea.getBounds().intersects(
+ targetRegionDelegate.mArea.getBounds()) == false;
+
+ }
+
+ /*package*/ static void translate(Region thisRegion, int dx, int dy, Region dst) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return;
+ }
+
+ Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
+ if (targetRegionDelegate == null) {
+ return;
+ }
+
+ if (regionDelegate.mArea.isEmpty()) {
+ targetRegionDelegate.mArea = new Area();
+ } else {
+ targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
+ AffineTransform mtx = new AffineTransform();
+ mtx.translate(dx, dy);
+ targetRegionDelegate.mArea.transform(mtx);
+ }
+ }
+
+ /*package*/ static void scale(Region thisRegion, float scale, Region dst) {
+ Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+ if (regionDelegate == null) {
+ return;
+ }
+
+ Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
+ if (targetRegionDelegate == null) {
+ return;
+ }
+
+ if (regionDelegate.mArea.isEmpty()) {
+ targetRegionDelegate.mArea = new Area();
+ } else {
+ targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
+ AffineTransform mtx = new AffineTransform();
+ mtx.scale(scale, scale);
+ targetRegionDelegate.mArea.transform(mtx);
+ }
+ }
+
/*package*/ static int nativeConstructor() {
Region_Delegate newDelegate = new Region_Delegate();
return sManager.addDelegate(newDelegate);
diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java
new file mode 100644
index 0000000..7fa1679
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 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.util;
+
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link XmlUtils}
+ *
+ * Through the layoutlib_create tool, the original methods of XmlUtils have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class XmlUtils_Delegate {
+ /*package*/ static final int convertValueToInt(CharSequence charSeq, int defaultValue) {
+ if (null == charSeq)
+ return defaultValue;
+
+ String nm = charSeq.toString();
+
+ // This code is copied from the original implementation. The issue is that
+ // The Dalvik libraries are able to handle Integer.parse("XXXXXXXX", 16) where XXXXXXX
+ // is > 80000000 but the Java VM cannot.
+
+ int sign = 1;
+ int index = 0;
+ int len = nm.length();
+ int base = 10;
+
+ if ('-' == nm.charAt(0)) {
+ sign = -1;
+ index++;
+ }
+
+ if ('0' == nm.charAt(index)) {
+ // Quick check for a zero by itself
+ if (index == (len - 1))
+ return 0;
+
+ char c = nm.charAt(index + 1);
+
+ if ('x' == c || 'X' == c) {
+ index += 2;
+ base = 16;
+ } else {
+ index++;
+ base = 8;
+ }
+ }
+ else if ('#' == nm.charAt(index)) {
+ index++;
+ base = 16;
+ }
+
+ return ((int)Long.parseLong(nm.substring(index), base)) * sign;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index e1bf925..0990cef 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -142,16 +142,6 @@
}
@Override
- public void error(String tag, Throwable t) {
- String message = t.getMessage();
- if (message == null) {
- message = t.getClass().getName();
- }
-
- System.err.println(message);
- }
-
- @Override
public void error(String tag, String message, Throwable throwable) {
System.err.println(message);
}
@@ -195,7 +185,8 @@
Capability.RENDER,
Capability.EMBEDDED_LAYOUT,
Capability.VIEW_MANIPULATION,
- Capability.ANIMATE);
+ Capability.PLAY_ANIMATION,
+ Capability.ANIMATED_VIEW_MANIPULATION);
BridgeAssetManager.initSystem();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
index 791e53b..194687e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
@@ -48,6 +48,7 @@
public final static String PREFIX_ANDROID = "android:";
+ public final static String RES_ANIMATOR = "animator";
public final static String RES_STYLE = "style";
public final static String RES_ATTR = "attr";
public final static String RES_DIMEN = "dimen";
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 7269227..fb79473 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -92,7 +92,7 @@
// cache for TypedArray generated from IStyleResourceValue object
private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
- private BridgeInflater mInflater;
+ private BridgeInflater mBridgeInflater;
private final IProjectCallback mProjectCallback;
private BridgeContentResolver mContentResolver;
@@ -160,7 +160,7 @@
}
public void setBridgeInflater(BridgeInflater inflater) {
- mInflater = inflater;
+ mBridgeInflater = inflater;
}
public void addViewKey(View view, Object viewKey) {
@@ -221,7 +221,7 @@
@Override
public LayoutInflater getLayoutInflater() {
- return mInflater;
+ return mBridgeInflater;
}
// ------------ Context methods
@@ -244,7 +244,7 @@
@Override
public Object getSystemService(String service) {
if (LAYOUT_INFLATER_SERVICE.equals(service)) {
- return mInflater;
+ return mBridgeInflater;
}
// AutoCompleteTextView and MultiAutoCompleteTextView want a window
@@ -493,12 +493,12 @@
/**
* Resolves the value of a resource, if the value references a theme or resource value.
* <p/>
- * This method ensures that it returns a {@link IResourceValue} object that does not
+ * This method ensures that it returns a {@link ResourceValue} object that does not
* reference another resource.
* If the resource cannot be resolved, it returns <code>null</code>.
* <p/>
* If a value that does not need to be resolved is given, the method will return a new
- * instance of IResourceValue that contains the input value.
+ * instance of {@link ResourceValue} that contains the input value.
*
* @param type the type of the resource
* @param name the name of the attribute containing this value.
@@ -510,11 +510,11 @@
return null;
}
- // get the IResourceValue referenced by this value
+ // get the ResourceValue referenced by this value
ResourceValue resValue = findResValue(value, false /*forceFrameworkOnly*/);
// if resValue is null, but value is not null, this means it was not a reference.
- // we return the name/value wrapper in a IResourceValue. the isFramework flag doesn't
+ // we return the name/value wrapper in a ResourceValue. the isFramework flag doesn't
// matter.
if (resValue == null) {
return new ResourceValue(type, name, value, false /*isFramework*/);
@@ -525,9 +525,9 @@
}
/**
- * Returns the {@link IResourceValue} referenced by the value of <var>value</var>.
+ * Returns the {@link ResourceValue} referenced by the value of <var>value</var>.
* <p/>
- * This method ensures that it returns a {@link IResourceValue} object that does not
+ * This method ensures that it returns a {@link ResourceValue} object that does not
* reference another resource.
* If the resource cannot be resolved, it returns <code>null</code>.
* <p/>
@@ -535,7 +535,7 @@
* value.
*
* @param value the value containing the reference to resolve.
- * @return a {@link IResourceValue} object or <code>null</code>
+ * @return a {@link ResourceValue} object or <code>null</code>
*/
public ResourceValue resolveResValue(ResourceValue value) {
if (value == null) {
@@ -547,7 +547,7 @@
return value;
}
- // else attempt to find another IResourceValue referenced by this one.
+ // else attempt to find another ResourceValue referenced by this one.
ResourceValue resolvedValue = findResValue(value.getValue(), value.isFramework());
// if the value did not reference anything, then we simply return the input value
@@ -560,7 +560,7 @@
}
/**
- * Searches for, and returns a {@link IResourceValue} by its reference.
+ * Searches for, and returns a {@link ResourceValue} by its reference.
* <p/>
* The reference format can be:
* <pre>@resType/resName</pre>
@@ -577,7 +577,7 @@
* @param reference the resource reference to search for.
* @param forceFrameworkOnly if true all references are considered to be toward framework
* resource even if the reference does not include the android: prefix.
- * @return a {@link IResourceValue} or <code>null</code>.
+ * @return a {@link ResourceValue} or <code>null</code>.
*/
ResourceValue findResValue(String reference, boolean forceFrameworkOnly) {
if (reference == null) {
@@ -591,7 +591,7 @@
boolean frameworkOnly = false;
- // eleminate the prefix from the string
+ // eliminate the prefix from the string
if (reference.startsWith(BridgeConstants.PREFIX_ANDROID_THEME_REF)) {
frameworkOnly = true;
reference = reference.substring(BridgeConstants.PREFIX_ANDROID_THEME_REF.length());
@@ -670,14 +670,14 @@
}
/**
- * Searches for, and returns a {@link IResourceValue} by its name, and type.
+ * Searches for, and returns a {@link ResourceValue} by its name, and type.
* @param resType the type of the resource
* @param resName the name of the resource
* @param frameworkOnly if <code>true</code>, the method does not search in the
* project resources
*/
private ResourceValue findResValue(String resType, String resName, boolean frameworkOnly) {
- // map of IResouceValue for the given type
+ // map of ResouceValue for the given type
Map<String, ResourceValue> typeMap;
// if allowed, search in the project resources first.
@@ -701,6 +701,13 @@
}
// didn't find the resource anywhere.
+ // This is normal if the resource is an ID that is generated automatically.
+ // For other resources, we output a warning
+ if ("+id".equals(resType) == false && "+android:id".equals(resType) == false) { //$NON-NLS-1$ //$NON-NLS-2$
+ Bridge.getLog().warning("resources", //$NON-NLS-1$
+ "Couldn't resolve resource @" +
+ (frameworkOnly ? "android:" : "") + resType + "/" + resName);
+ }
return null;
}
@@ -739,11 +746,11 @@
}
/**
- * Returns the {@link IResourceValue} matching a given name in a given style. If the
+ * Returns the {@link ResourceValue} matching a given name in a given style. If the
* item is not directly available in the style, the method looks in its parent style.
* @param style the style to search in
* @param itemName the name of the item to search for.
- * @return the {@link IResourceValue} object or <code>null</code>
+ * @return the {@link ResourceValue} object or <code>null</code>
*/
public ResourceValue findItemInStyle(StyleResourceValue style, String itemName) {
ResourceValue item = style.findValue(itemName);
@@ -871,8 +878,8 @@
return null;
}
- int getFrameworkIdValue(String idName, int defValue) {
- Integer value = Bridge.getResourceValue(BridgeConstants.RES_ID, idName);
+ int getFrameworkResourceValue(String resType, String resName, int defValue) {
+ Integer value = Bridge.getResourceValue(resType, resName);
if (value != null) {
return value.intValue();
}
@@ -880,9 +887,9 @@
return defValue;
}
- int getProjectIdValue(String idName, int defValue) {
+ int getProjectResourceValue(String resType, String resName, int defValue) {
if (mProjectCallback != null) {
- Integer value = mProjectCallback.getResourceValue(BridgeConstants.RES_ID, idName);
+ Integer value = mProjectCallback.getResourceValue(resType, resName);
if (value != null) {
return value.intValue();
}
@@ -1303,4 +1310,15 @@
public Context getApplicationContext() {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void startActivities(Intent[] arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isRestricted() {
+ return false;
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
index 1b59621..36aa335 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
@@ -178,8 +178,10 @@
return inflate(bridgeParser, root);
} catch (Exception e) {
- Bridge.getLog().error(null, e);
- // return null below.
+ Bridge.getLog().error(null,
+ "Failed to parse file " + f.getAbsolutePath(), e);
+
+ return null;
}
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 2ea5281..a56800c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -43,7 +43,6 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
-import java.io.IOException;
import java.io.InputStream;
/**
@@ -173,14 +172,13 @@
return ColorStateList.createFromXml(this,
new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(null, e);
- } catch (FileNotFoundException e) {
- // will not happen, since we pre-check
- } catch (IOException e) {
- Bridge.getLog().error(null, e);
- }
+ } catch (Exception e) {
+ // this is an error and not warning since the file existence is checked before
+ // attempting to parse it.
+ Bridge.getLog().error(null, "Failed to parse file " + value, e);
+ return null;
+ }
} else {
// try to load the color state list from an int
try {
@@ -245,7 +243,8 @@
return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
}
} catch (XmlPullParserException e) {
- Bridge.getLog().error(null, e);
+ Bridge.getLog().error(null,
+ "Failed to configure parser for " + value.getValue(), e);
// we'll return null below.
} catch (FileNotFoundException e) {
// this shouldn't happen since we check above.
@@ -279,7 +278,8 @@
return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
}
} catch (XmlPullParserException e) {
- Bridge.getLog().error(null, e);
+ Bridge.getLog().error(null,
+ "Failed to configure parser for " + value.getValue(), e);
// we'll return null below.
} catch (FileNotFoundException e) {
// this shouldn't happen since we check above.
@@ -294,7 +294,6 @@
return null;
}
-
@Override
public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
return mContext.obtainStyledAttributes(set, attrs);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 6ae7e03..7f11897 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -43,25 +43,25 @@
*/
public final class BridgeTypedArray extends TypedArray {
- private BridgeResources mResources;
+ private BridgeResources mBridgeResources;
private BridgeContext mContext;
- private ResourceValue[] mData;
+ private ResourceValue[] mResourceData;
private String[] mNames;
private final boolean mPlatformFile;
public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
boolean platformFile) {
super(null, null, null, 0);
- mResources = resources;
+ mBridgeResources = resources;
mContext = context;
mPlatformFile = platformFile;
- mData = new ResourceValue[len];
+ mResourceData = new ResourceValue[len];
mNames = new String[len];
}
/** A bridge-specific method that sets a value in the type array */
public void bridgeSetValue(int index, String name, ResourceValue value) {
- mData[index] = value;
+ mResourceData[index] = value;
mNames[index] = name;
}
@@ -75,7 +75,7 @@
// fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
// first count the array size
int count = 0;
- for (ResourceValue data : mData) {
+ for (ResourceValue data : mResourceData) {
if (data != null) {
count++;
}
@@ -87,8 +87,8 @@
// fill the array with the indices.
int index = 1;
- for (int i = 0 ; i < mData.length ; i++) {
- if (mData[i] != null) {
+ for (int i = 0 ; i < mResourceData.length ; i++) {
+ if (mResourceData[i] != null) {
mIndices[index++] = i;
}
}
@@ -99,7 +99,7 @@
*/
@Override
public int length() {
- return mData.length;
+ return mResourceData.length;
}
/**
@@ -107,7 +107,7 @@
*/
@Override
public Resources getResources() {
- return mResources;
+ return mBridgeResources;
}
/**
@@ -120,9 +120,9 @@
*/
@Override
public CharSequence getText(int index) {
- if (mData[index] != null) {
+ if (mResourceData[index] != null) {
// FIXME: handle styled strings!
- return mData[index].getValue();
+ return mResourceData[index].getValue();
}
return null;
@@ -138,8 +138,8 @@
*/
@Override
public String getString(int index) {
- if (mData[index] != null) {
- return mData[index].getValue();
+ if (mResourceData[index] != null) {
+ return mResourceData[index].getValue();
}
return null;
@@ -155,11 +155,11 @@
*/
@Override
public boolean getBoolean(int index, boolean defValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return defValue;
}
- String s = mData[index].getValue();
+ String s = mResourceData[index].getValue();
if (s != null) {
return XmlUtils.convertValueToBoolean(s, defValue);
}
@@ -177,11 +177,11 @@
*/
@Override
public int getInt(int index, int defValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return defValue;
}
- String s = mData[index].getValue();
+ String s = mResourceData[index].getValue();
try {
return (s == null) ? defValue : XmlUtils.convertValueToInt(s, defValue);
@@ -225,11 +225,11 @@
*/
@Override
public float getFloat(int index, float defValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return defValue;
}
- String s = mData[index].getValue();
+ String s = mResourceData[index].getValue();
if (s != null) {
try {
@@ -259,11 +259,11 @@
*/
@Override
public int getColor(int index, int defValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return defValue;
}
- String s = mData[index].getValue();
+ String s = mResourceData[index].getValue();
try {
return ResourceHelper.getColor(s);
} catch (NumberFormatException e) {
@@ -288,11 +288,11 @@
*/
@Override
public ColorStateList getColorStateList(int index) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return null;
}
- String value = mData[index].getValue();
+ String value = mResourceData[index].getValue();
if (value == null) {
return null;
@@ -322,17 +322,18 @@
} catch (Exception e) {
// this is an error and not warning since the file existence is checked before
// attempting to parse it.
- Bridge.getLog().error(null, e);
+ Bridge.getLog().error(null, "Failed to parse file " + value, e);
- // return null below.
+ return null;
}
// looks like were unable to resolve the color value.
- assert false;
Bridge.getLog().warning(null, String.format(
"Unable to resolve color value \"%1$s\" in attribute \"%2$s\"",
value, mNames[index]));
+ assert false;
+
return null;
}
@@ -347,11 +348,11 @@
*/
@Override
public int getInteger(int index, int defValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return defValue;
}
- String s = mData[index].getValue();
+ String s = mResourceData[index].getValue();
if (s != null) {
try {
@@ -386,11 +387,11 @@
*/
@Override
public float getDimension(int index, float defValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return defValue;
}
- String s = mData[index].getValue();
+ String s = mResourceData[index].getValue();
if (s == null) {
return defValue;
@@ -402,15 +403,16 @@
}
if (ResourceHelper.stringToFloat(s, mValue)) {
- return mValue.getDimension(mResources.mMetrics);
+ return mValue.getDimension(mBridgeResources.mMetrics);
}
// looks like we were unable to resolve the dimension value
- assert false;
Bridge.getLog().warning(null, String.format(
"Unable to resolve dimension value \"%1$s\" in attribute \"%2$s\"",
s, mNames[index]));
+ assert false;
+
return defValue;
}
@@ -456,11 +458,11 @@
*/
@Override
public int getDimensionPixelSize(int index, int defValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return defValue;
}
- String s = mData[index].getValue();
+ String s = mResourceData[index].getValue();
if (s == null) {
return defValue;
@@ -522,11 +524,11 @@
*/
@Override
public float getFraction(int index, int base, int pbase, float defValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return defValue;
}
- String value = mData[index].getValue();
+ String value = mResourceData[index].getValue();
if (value == null) {
return defValue;
}
@@ -536,11 +538,12 @@
}
// looks like we were unable to resolve the fraction value
- assert false;
Bridge.getLog().warning(null, String.format(
"Unable to resolve fraction value \"%1$s\" in attribute \"%2$s\"",
value, mNames[index]));
+ assert false;
+
return defValue;
}
@@ -560,8 +563,8 @@
*/
@Override
public int getResourceId(int index, int defValue) {
- // get the IResource for this index
- ResourceValue resValue = mData[index];
+ // get the Resource for this index
+ ResourceValue resValue = mResourceData[index];
// no data, return the default value.
if (resValue == null) {
@@ -574,19 +577,21 @@
return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
}
- // if the attribute was a reference to an id, and not a declaration of an id (@+id), then
- // the xml attribute value was "resolved" which leads us to a IResourceValue with
- // getType() returning "id" and getName() returning the id name
+ // if the attribute was a reference to a resource, and not a declaration of an id (@+id),
+ // then the xml attribute value was "resolved" which leads us to a ResourceValue with a
+ // valid getType() and getName() returning a resource name.
// (and getValue() returning null!). We need to handle this!
- if (resValue.getType() != null && resValue.getType().equals(BridgeConstants.RES_ID)) {
+ if (resValue.getType() != null && resValue.getType().startsWith("@+") == false) {
// if this is a framework id
if (mPlatformFile || resValue.isFramework()) {
// look for idName in the android R classes
- return mContext.getFrameworkIdValue(resValue.getName(), defValue);
+ return mContext.getFrameworkResourceValue(
+ resValue.getType(), resValue.getName(), defValue);
}
// look for idName in the project R class.
- return mContext.getProjectIdValue(resValue.getName(), defValue);
+ return mContext.getProjectResourceValue(
+ resValue.getType(), resValue.getName(), defValue);
}
// else, try to get the value, and resolve it somehow.
@@ -623,11 +628,11 @@
// if this is a framework id
if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
// look for idName in the android R classes
- return mContext.getFrameworkIdValue(idName, defValue);
+ return mContext.getFrameworkResourceValue(BridgeConstants.RES_ID, idName, defValue);
}
// look for idName in the project R class.
- return mContext.getProjectIdValue(idName, defValue);
+ return mContext.getProjectResourceValue(BridgeConstants.RES_ID, idName, defValue);
}
// not a direct id valid reference? resolve it
@@ -644,9 +649,11 @@
return idValue.intValue();
}
- assert false;
Bridge.getLog().warning(null, String.format(
"Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]));
+
+ assert false;
+
return defValue;
}
@@ -662,28 +669,29 @@
*/
@Override
public Drawable getDrawable(int index) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return null;
}
- ResourceValue value = mData[index];
+ ResourceValue value = mResourceData[index];
String stringValue = value.getValue();
if (stringValue == null || BridgeConstants.REFERENCE_NULL.equals(stringValue)) {
return null;
}
- Drawable d = ResourceHelper.getDrawable(value, mContext, mData[index].isFramework());
+ Drawable d = ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
if (d != null) {
return d;
}
// looks like we were unable to resolve the drawable
- assert false;
Bridge.getLog().warning(null, String.format(
"Unable to resolve drawable \"%1$s\" in attribute \"%2$s\"", stringValue,
mNames[index]));
+ assert false;
+
return null;
}
@@ -700,18 +708,18 @@
*/
@Override
public CharSequence[] getTextArray(int index) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return null;
}
- String value = mData[index].getValue();
+ String value = mResourceData[index].getValue();
if (value != null) {
return new CharSequence[] { value };
}
Bridge.getLog().warning(null, String.format(
String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
- index, mData[index].getName())));
+ index, mResourceData[index].getName())));
return null;
}
@@ -727,11 +735,11 @@
*/
@Override
public boolean getValue(int index, TypedValue outValue) {
- if (mData[index] == null) {
+ if (mResourceData[index] == null) {
return false;
}
- String s = mData[index].getValue();
+ String s = mResourceData[index].getValue();
return ResourceHelper.stringToFloat(s, outValue);
}
@@ -745,7 +753,7 @@
*/
@Override
public boolean hasValue(int index) {
- return mData[index] != null;
+ return mResourceData[index] != null;
}
/**
@@ -792,6 +800,6 @@
@Override
public String toString() {
- return mData.toString();
+ return mResourceData.toString();
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
index 125c1e6..033e065 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
@@ -28,7 +28,7 @@
import android.os.Message;
import android.os.Handler_Delegate.IHandlerCallback;
-import java.util.LinkedList;
+import java.util.PriorityQueue;
import java.util.Queue;
/**
@@ -45,7 +45,7 @@
*/
public abstract class AnimationThread extends Thread {
- private static class MessageBundle {
+ private static class MessageBundle implements Comparable<MessageBundle> {
final Handler mTarget;
final Message mMessage;
final long mUptimeMillis;
@@ -55,11 +55,18 @@
mMessage = message;
mUptimeMillis = uptimeMillis;
}
+
+ public int compareTo(MessageBundle bundle) {
+ if (mUptimeMillis < bundle.mUptimeMillis) {
+ return -1;
+ }
+ return 1;
+ }
}
private final RenderSessionImpl mSession;
- private Queue<MessageBundle> mQueue = new LinkedList<MessageBundle>();
+ private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>();
private final IAnimationListener mListener;
public AnimationThread(RenderSessionImpl scene, String threadName,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 025a318..5d5f2a1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -365,7 +365,7 @@
}
// log it
- mParams.getLog().error("Scene inflate failed", t);
+ mParams.getLog().error(null, "Scene inflate failed", t);
return ERROR_INFLATION.createResult(t.getMessage(), t);
}
@@ -481,7 +481,7 @@
}
// log it
- mParams.getLog().error("Scene Render failed", t);
+ mParams.getLog().error(null, "Scene Render failed", t);
return ERROR_UNKNOWN.createResult(t.getMessage(), t);
}
@@ -505,14 +505,18 @@
ResourceValue animationResource = null;
int animationId = 0;
if (isFrameworkAnimation) {
- animationResource = mContext.getFrameworkResource("anim", animationName);
+ animationResource = mContext.getFrameworkResource(BridgeConstants.RES_ANIMATOR,
+ animationName);
if (animationResource != null) {
- animationId = Bridge.getResourceValue("anim", animationName);
+ animationId = Bridge.getResourceValue(BridgeConstants.RES_ANIMATOR,
+ animationName);
}
} else {
- animationResource = mContext.getProjectResource("anim", animationName);
+ animationResource = mContext.getProjectResource(BridgeConstants.RES_ANIMATOR,
+ animationName);
if (animationResource != null) {
- animationId = mContext.getProjectCallback().getResourceValue("anim", animationName);
+ animationId = mContext.getProjectCallback().getResourceValue(
+ BridgeConstants.RES_ANIMATOR, animationName);
}
}
@@ -630,7 +634,7 @@
* @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
*/
public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
- Map<String, String> layoutParamsMap, IAnimationListener listener) {
+ Map<String, String> layoutParamsMap, final IAnimationListener listener) {
checkLock();
invalidateRenderingSize();
@@ -647,42 +651,73 @@
if (listener != null) {
final LayoutParams params = layoutParams;
- new AnimationThread(this, "moveChild", listener) {
- @Override
- public Result preAnimation() {
- // set up the transition for the previous parent.
- LayoutTransition removeTransition = new LayoutTransition();
- previousParent.setLayoutTransition(removeTransition);
+ // there is no support for animating views across layouts, so in case the new and old
+ // parent views are different we fake the animation through a no animation thread.
+ if (previousParent != newParentView) {
+ new Thread("not animated moveChild") {
+ @Override
+ public void run() {
+ Result result = moveView(previousParent, newParentView, childView, index,
+ params);
+ if (result.isSuccess() == false) {
+ listener.done(result);
+ }
- // no fade-out. Because we can't rely on layout transition listeners when
- // there is no Animator at all, instead we keep the animator but set its
- // duration to 0.
- // Note: Cannot user Animation.setDuration() directly. Have to set it
- // on the LayoutTransition.
- removeTransition.setDuration(LayoutTransition.DISAPPEARING, 0);
+ // ready to do the work, acquire the scene.
+ result = acquire(250);
+ if (result.isSuccess() == false) {
+ listener.done(result);
+ return;
+ }
- if (previousParent != newParentView) {
- // different parent, set a Layout transition on the new parent.
- newParentView.setLayoutTransition(new LayoutTransition());
+ try {
+ result = render();
+ if (result.isSuccess()) {
+ listener.onNewFrame(RenderSessionImpl.this.getSession());
+ }
+ } finally {
+ release();
+ }
+
+ listener.done(result);
+ }
+ }.start();
+ } else {
+ new AnimationThread(this, "moveChild", listener) {
+
+ @Override
+ public Result preAnimation() {
+ // set up the transition for the parent.
+ LayoutTransition transition = new LayoutTransition();
+ previousParent.setLayoutTransition(transition);
+
+ // tweak the animation durations and start delays (to match the duration of
+ // animation playing just before).
+ // Note: Cannot user Animation.setDuration() directly. Have to set it
+ // on the LayoutTransition.
+ transition.setDuration(LayoutTransition.DISAPPEARING, 100);
+ // CHANGE_DISAPPEARING plays after DISAPPEARING
+ transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
+
+ transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
+
+ transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
+ // CHANGE_APPEARING plays after CHANGE_APPEARING
+ transition.setStartDelay(LayoutTransition.APPEARING, 100);
+
+ transition.setDuration(LayoutTransition.APPEARING, 100);
+
+ return moveView(previousParent, newParentView, childView, index, params);
}
- // no fade-in. Because we can't rely on layout transition listeners when
- // there is no Animator at all, instead we keep the animator but set its
- // duration to 0.
- // Note: Cannot user Animation.setDuration() directly. Have to set it
- // on the LayoutTransition.
- newParentView.getLayoutTransition().setDuration(LayoutTransition.APPEARING, 0);
-
- return moveView(previousParent, newParentView, childView, index, params);
- }
-
- @Override
- public void postAnimation() {
- previousParent.setLayoutTransition(null);
- newParentView.setLayoutTransition(null);
- }
- }.start();
+ @Override
+ public void postAnimation() {
+ previousParent.setLayoutTransition(null);
+ newParentView.setLayoutTransition(null);
+ }
+ }.start();
+ }
// always return success since the real status will come through the listener.
return SUCCESS.createResult(layoutParams);
@@ -707,7 +742,7 @@
*
* @param previousParent the previous parent, still owning the child at the time of the call.
* @param newParent the new parent
- * @param view the view to move
+ * @param movedView the view to move
* @param index the new location in the new parent
* @param params an option (can be null) {@link LayoutParams} instance.
*
@@ -715,12 +750,12 @@
* {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
* adding views.
*/
- private Result moveView(ViewGroup previousParent, final ViewGroup newParent, View view,
- final int index, final LayoutParams params) {
+ private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
+ final View movedView, final int index, final LayoutParams params) {
try {
// check if there is a transition on the previousParent.
- LayoutTransition transition = previousParent.getLayoutTransition();
- if (transition != null) {
+ LayoutTransition previousTransition = previousParent.getLayoutTransition();
+ if (previousTransition != null) {
// in this case there is an animation. This means we have to wait for the child's
// parent reference to be null'ed out so that we can add it to the new parent.
// It is technically removed right before the DISAPPEARING animation is done (if
@@ -730,48 +765,50 @@
// parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
// adding the child or the child will appear in its new location before the
// other children have made room for it.
- // If the parents are different, then we can add the child to its new parent right
- // after the DISAPPEARING animation is done.
-
- final int waitForType = newParent == previousParent ?
- LayoutTransition.CHANGE_DISAPPEARING : LayoutTransition.DISAPPEARING;
// add a listener to the transition to be notified of the actual removal.
- transition.addTransitionListener(new TransitionListener() {
+ previousTransition.addTransitionListener(new TransitionListener() {
+ private int mChangeDisappearingCount = 0;
public void startTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
- // don't care.
+ if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
+ mChangeDisappearingCount++;
+ }
}
public void endTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
- if (transitionType == waitForType) {
+ if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
+ mChangeDisappearingCount--;
+ }
+
+ if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
+ mChangeDisappearingCount == 0) {
// add it to the parentView in the correct location
if (params != null) {
- newParent.addView(view, index, params);
+ newParent.addView(movedView, index, params);
} else {
- newParent.addView(view, index);
+ newParent.addView(movedView, index);
}
-
}
}
});
// remove the view from the current parent.
- previousParent.removeView(view);
+ previousParent.removeView(movedView);
// and return since adding the view to the new parent is done in the listener.
return SUCCESS.createResult();
} else {
// standard code with no animation. pretty simple.
- previousParent.removeView(view);
+ previousParent.removeView(movedView);
// add it to the parentView in the correct location
if (params != null) {
- newParent.addView(view, index, params);
+ newParent.addView(movedView, index, params);
} else {
- newParent.addView(view, index);
+ newParent.addView(movedView, index);
}
return SUCCESS.createResult();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 5427f142..fb52c86 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -27,7 +27,6 @@
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
@@ -40,7 +39,6 @@
import android.util.TypedValue;
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -162,7 +160,7 @@
// URL is wrong, we'll return null below
} catch (IOException e) {
// failed to read the file, we'll return null below.
- Bridge.getLog().error(null, e);
+ Bridge.getLog().error(null, "Failed lot load " + file.getAbsolutePath(), e);
}
}
@@ -190,13 +188,14 @@
d = Drawable.createFromXml(context.getResources(),
new BridgeXmlBlockParser(parser, context, isFramework));
return d;
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(null, e);
- } catch (FileNotFoundException e) {
- // will not happen, since we pre-check
- } catch (IOException e) {
- Bridge.getLog().error(null, e);
+ } catch (Exception e) {
+ // this is an error and not warning since the file existence is checked before
+ // attempting to parse it.
+ Bridge.getLog().error(null, "Failed to parse file " + value, e);
}
+ } else {
+ Bridge.getLog().error(null,
+ String.format("File %s does not exist (or is not a file)", stringValue));
}
return null;
@@ -222,7 +221,7 @@
return new BitmapDrawable(context.getResources(), bitmap);
} catch (IOException e) {
// we'll return null below
- Bridge.getLog().error(null, e);
+ Bridge.getLog().error(null, "Failed lot load " + bmpFile.getAbsolutePath(), e);
}
} else {
// attempt to get a color from the value
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 6b589d7..4198006 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -97,6 +97,7 @@
"android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
"android.os.Handler#sendMessageAtTime",
"android.view.View#isInEditMode",
+ "com.android.internal.util.XmlUtils#convertValueToInt"
// TODO: comment out once DelegateClass is working
// "android.content.res.Resources$Theme#obtainStyledAttributes",
};
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 1a00507..f96a5ae 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -192,27 +192,16 @@
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
- mWifiStateMachine.setNetworkAvailable(false);
}
- @Override
- public void exit() {
- mWifiStateMachine.setNetworkAvailable(true);
- }
}
class InactiveState extends HierarchicalState {
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
- mWifiStateMachine.setNetworkAvailable(false);
}
- @Override
- public void exit() {
- mWifiStateMachine.setNetworkAvailable(true);
- }
}
-
class DisconnectedState extends HierarchicalState {
@Override
public void enter() {
@@ -336,4 +325,4 @@
if (DBG) Log.d(TAG, getName() + "\n");
}
}
-}
\ No newline at end of file
+}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 10faeda..8718117 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -299,10 +299,8 @@
static final int CMD_SET_FREQUENCY_BAND = 90;
/* Commands from/to the SupplicantStateTracker */
- /* Indicates whether a wifi network is available for connection */
- static final int CMD_SET_NETWORK_AVAILABLE = 111;
/* Reset the supplicant state tracker */
- static final int CMD_RESET_SUPPLICANT_STATE = 112;
+ static final int CMD_RESET_SUPPLICANT_STATE = 111;
/* Commands/events reported by WpsStateMachine */
@@ -1451,10 +1449,6 @@
setWifiEnabled(true);
}
- void setNetworkAvailable(boolean available) {
- sendMessage(obtainMessage(CMD_SET_NETWORK_AVAILABLE, available ? 1 : 0, 0));
- }
-
/********************************************************
* HSM states
*******************************************************/
@@ -1480,9 +1474,6 @@
case CMD_ENABLE_RSSI_POLL:
mEnableRssiPolling = (message.arg1 == 1);
break;
- case CMD_SET_NETWORK_AVAILABLE:
- mNetworkInfo.setIsAvailable(message.arg1 == 1);
- break;
/* Discard */
case CMD_LOAD_DRIVER:
case CMD_UNLOAD_DRIVER:
@@ -1873,6 +1864,8 @@
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
/* Initialize for connect mode operation at start */
mIsScanMode = false;
+ /* Wifi is available as long as we have a connection to supplicant */
+ mNetworkInfo.setIsAvailable(true);
}
@Override
public boolean processMessage(Message message) {
@@ -1886,6 +1879,7 @@
Log.e(TAG, "Failed to stop supplicant, issue kill");
WifiNative.killSupplicant();
}
+ mNetworkInfo.setIsAvailable(false);
handleNetworkDisconnect();
setWifiState(WIFI_STATE_DISABLING);
sendSupplicantConnectionChangedBroadcast(false);
@@ -1896,6 +1890,7 @@
Log.e(TAG, "Connection lost, restart supplicant");
WifiNative.killSupplicant();
WifiNative.closeSupplicantConnection();
+ mNetworkInfo.setIsAvailable(false);
handleNetworkDisconnect();
sendSupplicantConnectionChangedBroadcast(false);
mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
@@ -1975,6 +1970,11 @@
}
return HANDLED;
}
+
+ @Override
+ public void exit() {
+ mNetworkInfo.setIsAvailable(false);
+ }
}
class SupplicantStoppingState extends HierarchicalState {