Merge "HW audio encoder expects timestamp via kKeyTime from each input buffer" into gingerbread
diff --git a/api/current.xml b/api/current.xml
index e938246..a495d04 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -4024,6 +4024,17 @@
visibility="public"
>
</field>
+<field name="filterTouchesWhenObscured"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843460"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="finishOnCloseSystemDialogs"
type="int"
transient="false"
@@ -5861,17 +5872,6 @@
visibility="public"
>
</field>
-<field name="kraken_resource_pad61"
- type="int"
- transient="false"
- volatile="false"
- value="16843460"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="kraken_resource_pad7"
type="int"
transient="false"
@@ -78402,7 +78402,7 @@
type="float"
transient="false"
volatile="false"
- value="0.001f"
+ value="0.0010f"
static="true"
final="true"
deprecated="not deprecated"
@@ -140773,6 +140773,17 @@
visibility="public"
>
</field>
+<field name="INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.action.MEDIA_PLAY_FROM_SEARCH""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="INTENT_ACTION_MEDIA_SEARCH"
type="java.lang.String"
transient="false"
@@ -164852,6 +164863,29 @@
<parameter name="flags" type="int">
</parameter>
</method>
+<method name="formatDateRange"
+ return="java.util.Formatter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="formatter" type="java.util.Formatter">
+</parameter>
+<parameter name="startMillis" type="long">
+</parameter>
+<parameter name="endMillis" type="long">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+<parameter name="timeZone" type="java.lang.String">
+</parameter>
+</method>
<method name="formatDateTime"
return="java.lang.String"
abstract="false"
@@ -165345,7 +165379,7 @@
value="8192"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
@@ -181662,6 +181696,17 @@
visibility="public"
>
</method>
+<method name="getFlags"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getHistoricalEventTime"
return="long"
abstract="false"
@@ -182299,6 +182344,8 @@
</parameter>
<parameter name="source" type="int">
</parameter>
+<parameter name="flags" type="int">
+</parameter>
</method>
<method name="obtain"
return="android.view.MotionEvent"
@@ -182755,6 +182802,17 @@
visibility="public"
>
</field>
+<field name="FLAG_WINDOW_IS_OBSCURED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="MotionEvent.PointerCoords"
extends="java.lang.Object"
@@ -185477,6 +185535,17 @@
visibility="public"
>
</method>
+<method name="getFilterTouchesWhenObscured"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getFocusables"
return="java.util.ArrayList<android.view.View>"
abstract="false"
@@ -186765,6 +186834,19 @@
<parameter name="canvas" type="android.graphics.Canvas">
</parameter>
</method>
+<method name="onFilterTouchEventForSecurity"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
<method name="onFinishInflate"
return="void"
abstract="false"
@@ -187671,6 +187753,19 @@
<parameter name="length" type="int">
</parameter>
</method>
+<method name="setFilterTouchesWhenObscured"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
<method name="setFocusable"
return="void"
abstract="false"
@@ -225393,7 +225488,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
</parameter>
</method>
</interface>
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2acc4a0..7154aee 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1567,6 +1567,30 @@
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
/**
+ * Broadcast Action: A sticky broadcast that indicates a memory full
+ * condition on the device. This is intended for activities that want
+ * to be able to fill the data partition completely, leaving only
+ * enough free space to prevent system-wide SQLite failures.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ *
+ * {@hide}
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEVICE_STORAGE_FULL = "android.intent.action.DEVICE_STORAGE_FULL";
+ /**
+ * Broadcast Action: Indicates memory full condition on the device
+ * no longer exists.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ *
+ * {@hide}
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DEVICE_STORAGE_NOT_FULL = "android.intent.action.DEVICE_STORAGE_NOT_FULL";
+ /**
* Broadcast Action: Indicates low memory condition notification acknowledged by user
* and package management should be started.
* This is triggered by the user from the ACTION_DEVICE_STORAGE_LOW
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a857e58..32fb108 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1586,8 +1586,10 @@
sb.append(prefix); sb.append(" CPU: ");
formatTime(sb, userTime); sb.append("usr + ");
formatTime(sb, systemTime); sb.append("krn\n");
- sb.append(prefix); sb.append(" "); sb.append(starts);
- sb.append(" proc starts");
+ if (starts != 0) {
+ sb.append(prefix); sb.append(" "); sb.append(starts);
+ sb.append(" proc starts");
+ }
pw.println(sb.toString());
for (int e=0; e<numExcessive; e++) {
Uid.Proc.ExcessiveWake ew = ps.getExcessiveWake(e);
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index d20e89d..075da33 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -75,6 +75,22 @@
public static final String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
/**
+ * An intent to perform a search for music media and automatically play content from the
+ * result when possible. This can be fired, for example, by the result of a voice recognition
+ * command to listen to music.
+ * <p>
+ * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string
+ * that can contain any type of unstructured music search, like the name of an artist,
+ * an album, a song, a genre, or any combination of these.
+ * <p>
+ * Because this intent includes an open-ended unstructured search string, it makes the most
+ * sense for apps that can support large-scale search of music, such as services connected
+ * to an online database of music which can be streamed and played on the device.
+ */
+ public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH =
+ "android.media.action.MEDIA_PLAY_FROM_SEARCH";
+
+ /**
* The name of the Intent-extra used to define the artist
*/
public static final String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 78a384b..7c80420 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2961,31 +2961,31 @@
public static final String WTF_IS_FATAL = "wtf_is_fatal";
/**
- * Maximum age of entries kept by {@link android.os.IDropBox}.
+ * Maximum age of entries kept by {@link com.android.internal.os.IDropBoxManagerService}.
* @hide
*/
public static final String DROPBOX_AGE_SECONDS =
"dropbox_age_seconds";
/**
- * Maximum number of entry files which {@link android.os.IDropBox} will keep around.
+ * Maximum number of entry files which {@link com.android.internal.os.IDropBoxManagerService} will keep around.
* @hide
*/
public static final String DROPBOX_MAX_FILES =
"dropbox_max_files";
/**
- * Maximum amount of disk space used by {@link android.os.IDropBox} no matter what.
+ * Maximum amount of disk space used by {@link com.android.internal.os.IDropBoxManagerService} no matter what.
* @hide
*/
public static final String DROPBOX_QUOTA_KB =
"dropbox_quota_kb";
/**
- * Percent of free disk (excluding reserve) which {@link android.os.IDropBox} will use.
+ * Percent of free disk (excluding reserve) which {@link com.android.internal.os.IDropBoxManagerService} will use.
* @hide
*/
public static final String DROPBOX_QUOTA_PERCENT =
"dropbox_quota_percent";
/**
- * Percent of total disk which {@link android.os.IDropBox} will never dip into.
+ * Percent of total disk which {@link com.android.internal.os.IDropBoxManagerService} will never dip into.
* @hide
*/
public static final String DROPBOX_RESERVE_PERCENT =
@@ -3045,6 +3045,15 @@
"sys_storage_threshold_percentage";
/**
+ * Minimum bytes of free storage on the device before the data
+ * partition is considered full. By default, 1 MB is reserved
+ * to avoid system-wide SQLite disk full exceptions.
+ * @hide
+ */
+ public static final String SYS_STORAGE_FULL_THRESHOLD_BYTES =
+ "sys_storage_full_threshold_bytes";
+
+ /**
* The interval in milliseconds after which Wi-Fi is considered idle.
* When idle, it is possible for the device to be switched from Wi-Fi to
* the mobile data network.
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 57a72bf..2b083dc 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -30,6 +30,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
@@ -178,6 +179,9 @@
};
final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
+ {
+ mRequestedFormat = PixelFormat.RGB_565;
+ }
@Override
public boolean onAllowLockCanvas() {
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index dde0889..4e2c3c3 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -168,6 +168,12 @@
public static final int FORMAT_CAP_NOON = 0x00400;
public static final int FORMAT_NO_MIDNIGHT = 0x00800;
public static final int FORMAT_CAP_MIDNIGHT = 0x01000;
+ /**
+ * @deprecated Use
+ * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
+ * and pass in {@link Time#TIMEZONE_UTC Time.TIMEZONE_UTC} for the timeZone instead.
+ */
+ @Deprecated
public static final int FORMAT_UTC = 0x02000;
public static final int FORMAT_ABBREV_TIME = 0x04000;
public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
@@ -946,12 +952,12 @@
* {@link java.util.Formatter} instance and use the version of
* {@link #formatDateRange(Context, long, long, int) formatDateRange}
* that takes a {@link java.util.Formatter}.
- *
+ *
* @param context the context is required only if the time is shown
* @param startMillis the start time in UTC milliseconds
* @param endMillis the end time in UTC milliseconds
* @param flags a bit mask of options See
- * {@link #formatDateRange(Context, long, long, int) formatDateRange}
+ * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
* @return a string containing the formatted date/time range.
*/
public static String formatDateRange(Context context, long startMillis,
@@ -962,6 +968,29 @@
/**
* Formats a date or a time range according to the local conventions.
+ * <p>
+ * Note that this is a convenience method for formatting the date or
+ * time range in the local time zone. If you want to specify the time
+ * zone please use
+ * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}.
+ *
+ * @param context the context is required only if the time is shown
+ * @param formatter the Formatter used for formatting the date range.
+ * Note: be sure to call setLength(0) on StringBuilder passed to
+ * the Formatter constructor unless you want the results to accumulate.
+ * @param startMillis the start time in UTC milliseconds
+ * @param endMillis the end time in UTC milliseconds
+ * @param flags a bit mask of options See
+ * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
+ * @return a string containing the formatted date/time range.
+ */
+ public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
+ long endMillis, int flags) {
+ return formatDateRange(context, formatter, startMillis, endMillis, flags, null);
+ }
+
+ /**
+ * Formats a date or a time range according to the local conventions.
*
* <p>
* Example output strings (date formats in these examples are shown using
@@ -1076,8 +1105,9 @@
* FORMAT_24HOUR takes precedence.
*
* <p>
- * If FORMAT_UTC is set, then the UTC timezone is used for the start
- * and end milliseconds.
+ * If FORMAT_UTC is set, then the UTC time zone is used for the start
+ * and end milliseconds unless a time zone is specified. If a time zone
+ * is specified it will be used regardless of the FORMAT_UTC flag.
*
* <p>
* If FORMAT_ABBREV_TIME is set and 12-hour time format is used, then the
@@ -1109,11 +1139,13 @@
* @param startMillis the start time in UTC milliseconds
* @param endMillis the end time in UTC milliseconds
* @param flags a bit mask of options
- *
+ * @param timeZone the time zone to compute the string in. Use null for local
+ * or if the FORMAT_UTC flag is being used.
+ *
* @return the formatter with the formatted date/time range appended to the string buffer.
*/
public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
- long endMillis, int flags) {
+ long endMillis, int flags, String timeZone) {
Resources res = Resources.getSystem();
boolean showTime = (flags & FORMAT_SHOW_TIME) != 0;
boolean showWeekDay = (flags & FORMAT_SHOW_WEEKDAY) != 0;
@@ -1130,7 +1162,14 @@
// computation below that'd otherwise be thrown out.
boolean isInstant = (startMillis == endMillis);
- Time startDate = useUTC ? new Time(Time.TIMEZONE_UTC) : new Time();
+ Time startDate;
+ if (timeZone != null) {
+ startDate = new Time(timeZone);
+ } else if (useUTC) {
+ startDate = new Time(Time.TIMEZONE_UTC);
+ } else {
+ startDate = new Time();
+ }
startDate.set(startMillis);
Time endDate;
@@ -1139,7 +1178,13 @@
endDate = startDate;
dayDistance = 0;
} else {
- endDate = useUTC ? new Time(Time.TIMEZONE_UTC) : new Time();
+ if (timeZone != null) {
+ endDate = new Time(timeZone);
+ } else if (useUTC) {
+ endDate = new Time(Time.TIMEZONE_UTC);
+ } else {
+ endDate = new Time();
+ }
endDate.set(endMillis);
int startJulianDay = Time.getJulianDay(startMillis, startDate.gmtoff);
int endJulianDay = Time.getJulianDay(endMillis, endDate.gmtoff);
diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java
index 5be2a48..09cbbb8 100644
--- a/core/java/android/text/method/TextKeyListener.java
+++ b/core/java/android/text/method/TextKeyListener.java
@@ -246,8 +246,10 @@
private void initPrefs(Context context) {
final ContentResolver contentResolver = context.getContentResolver();
mResolver = new WeakReference<ContentResolver>(contentResolver);
- mObserver = new SettingsObserver();
- contentResolver.registerContentObserver(Settings.System.CONTENT_URI, true, mObserver);
+ if (mObserver == null) {
+ mObserver = new SettingsObserver();
+ contentResolver.registerContentObserver(Settings.System.CONTENT_URI, true, mObserver);
+ }
updatePrefs(contentResolver);
mPrefsInited = true;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 74318ba..78b9b5d 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -30,6 +30,7 @@
*/
public final class MotionEvent extends InputEvent implements Parcelable {
private static final long MS_PER_NS = 1000000;
+ private static final boolean TRACK_RECYCLED_LOCATION = false;
/**
* Bit mask of the parts of the action code that are the action itself.
@@ -155,7 +156,17 @@
@Deprecated
public static final int ACTION_POINTER_ID_SHIFT = 8;
- private static final boolean TRACK_RECYCLED_LOCATION = false;
+ /**
+ * This flag indicates that the window that received this motion event is partly
+ * or wholly obscured by another visible window above it. This flag is set to true
+ * even if the event did not directly pass through the obscured area.
+ * A security sensitive application can check this flag to identify situations in which
+ * a malicious application may have covered up part of its content for the purpose
+ * of misleading the user or hijacking touches. An appropriate response might be
+ * to drop the suspect touches or to take additional precautions to confirm the user's
+ * actual intent.
+ */
+ public static final int FLAG_WINDOW_IS_OBSCURED = 0x1;
/**
* Flag indicating the motion event intersected the top edge of the screen.
@@ -251,6 +262,7 @@
private float mYPrecision;
private int mEdgeFlags;
private int mMetaState;
+ private int mFlags;
private int mNumPointers;
private int mNumSamples;
@@ -338,20 +350,22 @@
* @param deviceId The id for the device that this event came from. An id of
* zero indicates that the event didn't come from a physical device; other
* numbers are arbitrary and you shouldn't depend on the values.
- * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
+ * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
* MotionEvent.
* @param source The source of this event.
+ * @param flags The motion event flags.
*/
static public MotionEvent obtain(long downTime, long eventTime,
int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords,
int metaState, float xPrecision, float yPrecision, int deviceId,
- int edgeFlags, int source) {
+ int edgeFlags, int source, int flags) {
MotionEvent ev = obtain(pointers, 1);
ev.mDeviceId = deviceId;
ev.mSource = source;
ev.mEdgeFlags = edgeFlags;
ev.mDownTimeNano = downTime * MS_PER_NS;
ev.mAction = action;
+ ev.mFlags = flags;
ev.mMetaState = metaState;
ev.mXOffset = 0;
ev.mYOffset = 0;
@@ -401,7 +415,7 @@
* @param deviceId The id for the device that this event came from. An id of
* zero indicates that the event didn't come from a physical device; other
* numbers are arbitrary and you shouldn't depend on the values.
- * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
+ * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
* MotionEvent.
*/
static public MotionEvent obtain(long downTime, long eventTime, int action,
@@ -413,6 +427,7 @@
ev.mEdgeFlags = edgeFlags;
ev.mDownTimeNano = downTime * MS_PER_NS;
ev.mAction = action;
+ ev.mFlags = 0;
ev.mMetaState = metaState;
ev.mXOffset = 0;
ev.mYOffset = 0;
@@ -462,7 +477,7 @@
* @param deviceId The id for the device that this event came from. An id of
* zero indicates that the event didn't come from a physical device; other
* numbers are arbitrary and you shouldn't depend on the values.
- * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
+ * @param edgeFlags A bitfield indicating which edges, if any, were touched by this
* MotionEvent.
*
* @deprecated Use {@link #obtain(long, long, int, float, float, float, float, int, float, float, int, int)}
@@ -509,6 +524,7 @@
ev.mEdgeFlags = o.mEdgeFlags;
ev.mDownTimeNano = o.mDownTimeNano;
ev.mAction = o.mAction;
+ ev.mFlags = o.mFlags;
ev.mMetaState = o.mMetaState;
ev.mXOffset = o.mXOffset;
ev.mYOffset = o.mYOffset;
@@ -540,6 +556,7 @@
ev.mEdgeFlags = o.mEdgeFlags;
ev.mDownTimeNano = o.mDownTimeNano;
ev.mAction = o.mAction;
+ o.mFlags = o.mFlags;
ev.mMetaState = o.mMetaState;
ev.mXOffset = o.mXOffset;
ev.mYOffset = o.mYOffset;
@@ -651,6 +668,15 @@
}
/**
+ * Gets the motion event flags.
+ *
+ * @see #FLAG_WINDOW_IS_OBSCURED
+ */
+ public final int getFlags() {
+ return mFlags;
+ }
+
+ /**
* Returns the time (in ms) when the user originally pressed down to start
* a stream of position events.
*/
@@ -1285,7 +1311,7 @@
/**
- * Sets the bitfield indicating which edges, if any, where touched by this
+ * Sets the bitfield indicating which edges, if any, were touched by this
* MotionEvent.
*
* @see #getEdgeFlags()
@@ -1480,6 +1506,7 @@
ev.mYPrecision = in.readFloat();
ev.mEdgeFlags = in.readInt();
ev.mMetaState = in.readInt();
+ ev.mFlags = in.readInt();
final int[] pointerIdentifiers = ev.mPointerIdentifiers;
for (int i = 0; i < NP; i++) {
@@ -1521,6 +1548,7 @@
out.writeFloat(mYPrecision);
out.writeInt(mEdgeFlags);
out.writeInt(mMetaState);
+ out.writeInt(mFlags);
final int[] pointerIdentifiers = mPointerIdentifiers;
for (int i = 0; i < NP; i++) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7332c16d..fe003a4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -542,6 +542,28 @@
* take care of redrawing the appropriate views until the animation completes.
* </p>
*
+ * <a name="Security"></a>
+ * <h3>Security</h3>
+ * <p>
+ * Sometimes it is essential that an application be able to verify that an action
+ * is being performed with the full knowledge and consent of the user, such as
+ * granting a permission request, making a purchase or clicking on an advertisement.
+ * Unfortunately, a malicious application could try to spoof the user into
+ * performing these actions, unaware, by concealing the intended purpose of the view.
+ * As a remedy, the framework offers a touch filtering mechanism that can be used to
+ * improve the security of views that provide access to sensitive functionality.
+ * </p><p>
+ * To enable touch filtering, call {@link #setFilterTouchesWhenObscured} or set the
+ * andoird:filterTouchesWhenObscured attribute to true. When enabled, the framework
+ * will discard touches that are received whenever the view's window is obscured by
+ * another visible window. As a result, the view will not receive touches whenever a
+ * toast, dialog or other window appears above the view's window.
+ * </p><p>
+ * For more fine-grained control over security, consider overriding the
+ * {@link #onFilterTouchEventForSecurity} method to implement your own security policy.
+ * See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
+ * </p>
+ *
* @attr ref android.R.styleable#View_background
* @attr ref android.R.styleable#View_clickable
* @attr ref android.R.styleable#View_contentDescription
@@ -550,6 +572,7 @@
* @attr ref android.R.styleable#View_id
* @attr ref android.R.styleable#View_fadingEdge
* @attr ref android.R.styleable#View_fadingEdgeLength
+ * @attr ref android.R.styleable#View_filterTouchesWhenObscured
* @attr ref android.R.styleable#View_fitsSystemWindows
* @attr ref android.R.styleable#View_isScrollContainer
* @attr ref android.R.styleable#View_focusable
@@ -711,7 +734,14 @@
*/
static final int SCROLLBARS_MASK = 0x00000300;
- // note 0x00000400 and 0x00000800 are now available for next flags...
+ /**
+ * Indicates that the view should filter touches when its window is obscured.
+ * Refer to the class comments for more information about this security feature.
+ * {@hide}
+ */
+ static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
+
+ // note flag value 0x00000800 is now available for next flags...
/**
* <p>This view doesn't show fading edges.</p>
@@ -2052,6 +2082,12 @@
viewFlagMasks |= KEEP_SCREEN_ON;
}
break;
+ case R.styleable.View_filterTouchesWhenObscured:
+ if (a.getBoolean(attr, false)) {
+ viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
+ viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
+ }
+ break;
case R.styleable.View_nextFocusLeft:
mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
break;
@@ -3389,6 +3425,35 @@
setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
}
+ /**
+ * Gets whether the framework should discard touches when the view's
+ * window is obscured by another visible window.
+ * Refer to the {@link View} security documentation for more details.
+ *
+ * @return True if touch filtering is enabled.
+ *
+ * @see #setFilterTouchesWhenObscured(boolean)
+ * @attr ref android.R.styleable#View_filterTouchesWhenObscured
+ */
+ @ViewDebug.ExportedProperty
+ public boolean getFilterTouchesWhenObscured() {
+ return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
+ }
+
+ /**
+ * Sets whether the framework should discard touches when the view's
+ * window is obscured by another visible window.
+ * Refer to the {@link View} security documentation for more details.
+ *
+ * @param enabled True if touch filtering should be enabled.
+ *
+ * @see #getFilterTouchesWhenObscured
+ * @attr ref android.R.styleable#View_filterTouchesWhenObscured
+ */
+ public void setFilterTouchesWhenObscured(boolean enabled) {
+ setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
+ FILTER_TOUCHES_WHEN_OBSCURED);
+ }
/**
* Returns whether this View is able to take focus.
@@ -3808,6 +3873,10 @@
* @return True if the event was handled by the view, false otherwise.
*/
public boolean dispatchTouchEvent(MotionEvent event) {
+ if (!onFilterTouchEventForSecurity(event)) {
+ return false;
+ }
+
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
@@ -3816,6 +3885,23 @@
}
/**
+ * Filter the touch event to apply security policies.
+ *
+ * @param event The motion event to be filtered.
+ * @return True if the event should be dispatched, false if the event should be dropped.
+ *
+ * @see #getFilterTouchesWhenObscured
+ */
+ public boolean onFilterTouchEventForSecurity(MotionEvent event) {
+ if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
+ && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
+ // Window is obscured, drop this touch.
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Pass a trackball motion event down to the focused view.
*
* @param event The motion event to be dispatched.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7159929..28bed3a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -822,6 +822,10 @@
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (!onFilterTouchEventForSecurity(ev)) {
+ return false;
+ }
+
final int action = ev.getAction();
final float xf = ev.getX();
final float yf = ev.getY();
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 659f9cd..76701a9 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -74,6 +74,8 @@
public final static int FLAG_MENU = 0x00000040;
public final static int FLAG_LAUNCHER = 0x00000080;
+ public final static int FLAG_INJECTED = 0x01000000;
+
public final static int FLAG_WOKE_HERE = 0x10000000;
public final static int FLAG_BRIGHT_HERE = 0x20000000;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d0dd6cc..3428206 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5817,7 +5817,10 @@
* Return true iff there is a selection inside this text view.
*/
public boolean hasSelection() {
- return getSelectionStart() != getSelectionEnd();
+ final int selectionStart = getSelectionStart();
+ final int selectionEnd = getSelectionEnd();
+
+ return selectionStart >= 0 && selectionStart != selectionEnd;
}
/**
@@ -7005,7 +7008,7 @@
return false;
}
- if (mText.length() > 0 && getSelectionStart() >= 0) {
+ if (mText.length() > 0 && hasSelection()) {
if (mText instanceof Editable && mInput != null) {
return true;
}
@@ -7019,7 +7022,7 @@
return false;
}
- if (mText.length() > 0 && getSelectionStart() >= 0) {
+ if (mText.length() > 0 && hasSelection()) {
return true;
}
@@ -7140,6 +7143,49 @@
int minOffset = selectionModifierCursorController.getMinTouchOffset();
int maxOffset = selectionModifierCursorController.getMaxTouchOffset();
+ if (minOffset == maxOffset) {
+ int offset = Math.max(0, Math.min(minOffset, mTransformed.length()));
+
+ // Tolerance, number of charaters around tapped position
+ final int range = 1;
+ final int max = mTransformed.length() - 1;
+
+ // 'Smart' word selection: detect position between words
+ for (int i = -range; i <= range; i++) {
+ int index = offset + i;
+ if (index >= 0 && index <= max) {
+ if (Character.isSpaceChar(mTransformed.charAt(index))) {
+ // Select current space
+ selectionStart = index;
+ selectionEnd = selectionStart + 1;
+
+ // Extend selection to maximum space range
+ while (selectionStart > 0 &&
+ Character.isSpaceChar(mTransformed.charAt(selectionStart - 1))) {
+ selectionStart--;
+ }
+ while (selectionEnd < max &&
+ Character.isSpaceChar(mTransformed.charAt(selectionEnd))) {
+ selectionEnd++;
+ }
+
+ Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
+ return;
+ }
+ }
+ }
+
+ // 'Smart' word selection: detect position at beginning or end of text.
+ if (offset <= range) {
+ Selection.setSelection((Spannable) mText, 0, 0);
+ return;
+ }
+ if (offset >= (max - range)) {
+ Selection.setSelection((Spannable) mText, max + 1, max + 1);
+ return;
+ }
+ }
+
long wordLimits = getWordLimitsAt(minOffset);
if (wordLimits >= 0) {
selectionStart = (int) (wordLimits >>> 32);
@@ -7220,21 +7266,22 @@
menu.add(0, ID_CUT, 0, com.android.internal.R.string.cut).
setOnMenuItemClickListener(handler).
setAlphabeticShortcut('x');
+ added = true;
}
if (canCopy()) {
menu.add(0, ID_COPY, 0, com.android.internal.R.string.copy).
setOnMenuItemClickListener(handler).
setAlphabeticShortcut('c');
+ added = true;
}
if (canPaste()) {
menu.add(0, ID_PASTE, 0, com.android.internal.R.string.paste).
setOnMenuItemClickListener(handler).
setAlphabeticShortcut('v');
+ added = true;
}
-
- added = true;
} else {
/*
if (!isFocused()) {
@@ -7313,11 +7360,10 @@
private boolean textIsOnlySpaces() {
final int length = mTransformed.length();
- for (int i=0; i<length; i++) {
- final char c = mTransformed.charAt(i);
- final int type = Character.getType(c);
- if (type != Character.SPACE_SEPARATOR)
+ for (int i = 0; i < length; i++) {
+ if (!Character.isSpaceChar(mTransformed.charAt(i))) {
return false;
+ }
}
return true;
}
@@ -7350,7 +7396,7 @@
/**
* Called when a context menu option for the text view is selected. Currently
* this will be one of: {@link android.R.id#selectAll},
- * {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText},
+ * {@link android.R.id#startSelectingText},
* {@link android.R.id#cut}, {@link android.R.id#copy},
* {@link android.R.id#paste}, {@link android.R.id#copyUrl},
* or {@link android.R.id#switchInputMethod}.
@@ -7394,7 +7440,37 @@
case ID_PASTE:
CharSequence paste = clip.getText();
- if (paste != null) {
+ if (paste != null && paste.length() > 0) {
+ // Paste adds/removes spaces before or after insertion as needed.
+
+ if (Character.isSpaceChar(paste.charAt(0))) {
+ if (min > 0 && Character.isSpaceChar(mTransformed.charAt(min - 1))) {
+ // Two spaces at beginning of paste: remove one
+ ((Editable) mText).replace(min - 1, min, "");
+ min = min - 1;
+ max = max - 1;
+ }
+ } else {
+ if (min > 0 && !Character.isSpaceChar(mTransformed.charAt(min - 1))) {
+ // No space at beginning of paste: add one
+ ((Editable) mText).replace(min, min, " ");
+ min = min + 1;
+ max = max + 1;
+ }
+ }
+
+ if (Character.isSpaceChar(paste.charAt(paste.length() - 1))) {
+ if (max < mText.length() && Character.isSpaceChar(mTransformed.charAt(max))) {
+ // Two spaces at end of paste: remove one
+ ((Editable) mText).replace(max, max + 1, "");
+ }
+ } else {
+ if (max < mText.length() && !Character.isSpaceChar(mTransformed.charAt(max))) {
+ // No space at end of paste: add one
+ ((Editable) mText).replace(max, max, " ");
+ }
+ }
+
Selection.setSelection((Spannable) mText, max);
((Editable) mText).replace(min, max, paste);
stopTextSelectionMode();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 566ed29..b73b78b 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -22,6 +22,8 @@
import android.net.TrafficStats;
import android.os.BatteryManager;
import android.os.BatteryStats;
+import android.os.Handler;
+import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Parcelable;
@@ -79,6 +81,38 @@
private final JournaledFile mFile;
+ static final int MSG_UPDATE_WAKELOCKS = 1;
+ static final int MSG_REPORT_POWER_CHANGE = 2;
+ static final long DELAY_UPDATE_WAKELOCKS = 15*1000;
+
+ public interface BatteryCallback {
+ public void batteryNeedsCpuUpdate();
+ public void batteryPowerChanged(boolean onBattery);
+ }
+
+ final class MyHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ BatteryCallback cb = mCallback;
+ switch (msg.what) {
+ case MSG_UPDATE_WAKELOCKS:
+ if (cb != null) {
+ cb.batteryNeedsCpuUpdate();
+ }
+ break;
+ case MSG_REPORT_POWER_CHANGE:
+ if (cb != null) {
+ cb.batteryPowerChanged(msg.arg1 != 0);
+ }
+ break;
+ }
+ }
+ }
+
+ private final MyHandler mHandler;
+
+ private BatteryCallback mCallback;
+
/**
* The statistics we have collected organized by uids.
*/
@@ -95,6 +129,9 @@
final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
= new SparseArray<ArrayList<StopwatchTimer>>();
+ // Last partial timers we use for distributing CPU usage.
+ final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
+
// These are the objects that will want to do something when the device
// is unplugged from power.
final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
@@ -240,6 +277,7 @@
// For debugging
public BatteryStatsImpl() {
mFile = null;
+ mHandler = null;
}
public static interface Unpluggable {
@@ -739,7 +777,9 @@
* State for keeping track of timing information.
*/
public static final class StopwatchTimer extends Timer {
+ final Uid mUid;
final ArrayList<StopwatchTimer> mTimerPool;
+
int mNesting;
/**
@@ -757,16 +797,24 @@
long mTimeout;
- StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
+ /**
+ * For partial wake locks, keep track of whether we are in the list
+ * to consume CPU cycles.
+ */
+ boolean mInList;
+
+ StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
ArrayList<Unpluggable> unpluggables, Parcel in) {
super(type, unpluggables, in);
+ mUid = uid;
mTimerPool = timerPool;
mUpdateTime = in.readLong();
}
- StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
+ StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
ArrayList<Unpluggable> unpluggables) {
super(type, unpluggables);
+ mUid = uid;
mTimerPool = timerPool;
}
@@ -1252,6 +1300,10 @@
mWakeLockNesting++;
}
if (uid >= 0) {
+ if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
+ Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
+ mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
+ }
getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type);
}
}
@@ -1267,10 +1319,112 @@
}
}
if (uid >= 0) {
+ if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
+ Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
+ mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
+ }
getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type);
}
}
+ public int startAddingCpuLocked() {
+ mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+
+ if (mScreenOn) {
+ return 0;
+ }
+
+ final int N = mPartialTimers.size();
+ if (N == 0) {
+ mLastPartialTimers.clear();
+ return 0;
+ }
+
+ // How many timers should consume CPU? Only want to include ones
+ // that have already been in the list.
+ for (int i=0; i<N; i++) {
+ StopwatchTimer st = mPartialTimers.get(i);
+ if (st.mInList) {
+ Uid uid = st.mUid;
+ // We don't include the system UID, because it so often
+ // holds wake locks at one request or another of an app.
+ if (uid != null && uid.mUid != Process.SYSTEM_UID) {
+ return 50;
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
+ final int N = mPartialTimers.size();
+ if (perc != 0) {
+ int num = 0;
+ for (int i=0; i<N; i++) {
+ StopwatchTimer st = mPartialTimers.get(i);
+ if (st.mInList) {
+ Uid uid = st.mUid;
+ // We don't include the system UID, because it so often
+ // holds wake locks at one request or another of an app.
+ if (uid != null && uid.mUid != Process.SYSTEM_UID) {
+ num++;
+ }
+ }
+ }
+ if (num != 0) {
+ for (int i=0; i<N; i++) {
+ StopwatchTimer st = mPartialTimers.get(i);
+ if (st.mInList) {
+ int myUTime = utime/num;
+ int mySTime = stime/num;
+ utime -= myUTime;
+ stime -= mySTime;
+ num--;
+ Uid uid = st.mUid;
+ if (uid != null && uid.mUid != Process.SYSTEM_UID) {
+ Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
+ proc.addCpuTimeLocked(myUTime, mySTime);
+ proc.addSpeedStepTimes(cpuSpeedTimes);
+ }
+ }
+ }
+ }
+
+ // Just in case, collect any lost CPU time.
+ if (utime != 0 || stime != 0) {
+ Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
+ if (uid != null) {
+ Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
+ proc.addCpuTimeLocked(utime, stime);
+ proc.addSpeedStepTimes(cpuSpeedTimes);
+ }
+ }
+ }
+
+ final int NL = mLastPartialTimers.size();
+ boolean diff = N != NL;
+ for (int i=0; i<NL && !diff; i++) {
+ diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
+ }
+ if (!diff) {
+ for (int i=0; i<NL; i++) {
+ mPartialTimers.get(i).mInList = true;
+ }
+ return;
+ }
+
+ for (int i=0; i<NL; i++) {
+ mLastPartialTimers.get(i).mInList = false;
+ }
+ mLastPartialTimers.clear();
+ for (int i=0; i<N; i++) {
+ StopwatchTimer st = mPartialTimers.get(i);
+ st.mInList = true;
+ mLastPartialTimers.add(st);
+ }
+ }
+
public void noteProcessDiedLocked(int uid, int pid) {
Uid u = mUidStats.get(uid);
if (u != null) {
@@ -1922,13 +2076,18 @@
public Uid(int uid) {
mUid = uid;
- mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables);
- mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables);
- mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables);
- mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
+ mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
null, mUnpluggables);
- mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables);
- mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables);
+ mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
+ null, mUnpluggables);
+ mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
+ null, mUnpluggables);
+ mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
+ null, mUnpluggables);
+ mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
+ null, mUnpluggables);
+ mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
+ null, mUnpluggables);
}
@Override
@@ -1996,7 +2155,7 @@
if (!mWifiTurnedOn) {
mWifiTurnedOn = true;
if (mWifiTurnedOnTimer == null) {
- mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON,
+ mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
null, mUnpluggables);
}
mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2016,7 +2175,7 @@
if (!mFullWifiLockOut) {
mFullWifiLockOut = true;
if (mFullWifiLockTimer == null) {
- mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK,
+ mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
null, mUnpluggables);
}
mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2036,7 +2195,7 @@
if (!mScanWifiLockOut) {
mScanWifiLockOut = true;
if (mScanWifiLockTimer == null) {
- mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK,
+ mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
null, mUnpluggables);
}
mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2056,7 +2215,7 @@
if (!mWifiMulticastEnabled) {
mWifiMulticastEnabled = true;
if (mWifiMulticastTimer == null) {
- mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
+ mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
null, mUnpluggables);
}
mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2076,7 +2235,7 @@
if (!mAudioTurnedOn) {
mAudioTurnedOn = true;
if (mAudioTurnedOnTimer == null) {
- mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON,
+ mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
null, mUnpluggables);
}
mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2096,7 +2255,7 @@
if (!mVideoTurnedOn) {
mVideoTurnedOn = true;
if (mVideoTurnedOnTimer == null) {
- mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON,
+ mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
null, mUnpluggables);
}
mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@@ -2456,42 +2615,42 @@
mTcpBytesSentAtLastUnplug = in.readLong();
mWifiTurnedOn = false;
if (in.readInt() != 0) {
- mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON,
+ mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
null, mUnpluggables, in);
} else {
mWifiTurnedOnTimer = null;
}
mFullWifiLockOut = false;
if (in.readInt() != 0) {
- mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK,
+ mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
null, mUnpluggables, in);
} else {
mFullWifiLockTimer = null;
}
mScanWifiLockOut = false;
if (in.readInt() != 0) {
- mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK,
+ mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
null, mUnpluggables, in);
} else {
mScanWifiLockTimer = null;
}
mWifiMulticastEnabled = false;
if (in.readInt() != 0) {
- mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
+ mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
null, mUnpluggables, in);
} else {
mWifiMulticastTimer = null;
}
mAudioTurnedOn = false;
if (in.readInt() != 0) {
- mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON,
+ mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
null, mUnpluggables, in);
} else {
mAudioTurnedOnTimer = null;
}
mVideoTurnedOn = false;
if (in.readInt() != 0) {
- mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON,
+ mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
null, mUnpluggables, in);
} else {
mVideoTurnedOnTimer = null;
@@ -2538,7 +2697,7 @@
return null;
}
- return new StopwatchTimer(type, pool, unpluggables, in);
+ return new StopwatchTimer(Uid.this, type, pool, unpluggables, in);
}
boolean reset() {
@@ -2614,7 +2773,7 @@
pool = new ArrayList<StopwatchTimer>();
mSensorTimers.put(mHandle, pool);
}
- return new StopwatchTimer(0, pool, unpluggables, in);
+ return new StopwatchTimer(Uid.this, 0, pool, unpluggables, in);
}
boolean reset() {
@@ -3416,21 +3575,24 @@
case WAKE_TYPE_PARTIAL:
t = wl.mTimerPartial;
if (t == null) {
- t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
+ t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
+ mPartialTimers, mUnpluggables);
wl.mTimerPartial = t;
}
return t;
case WAKE_TYPE_FULL:
t = wl.mTimerFull;
if (t == null) {
- t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
+ t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
+ mFullTimers, mUnpluggables);
wl.mTimerFull = t;
}
return t;
case WAKE_TYPE_WINDOW:
t = wl.mTimerWindow;
if (t == null) {
- t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
+ t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
+ mWindowTimers, mUnpluggables);
wl.mTimerWindow = t;
}
return t;
@@ -3457,7 +3619,7 @@
timers = new ArrayList<StopwatchTimer>();
mSensorTimers.put(sensor, timers);
}
- t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables);
+ t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mUnpluggables);
se.mTimer = t;
return t;
}
@@ -3530,25 +3692,26 @@
public BatteryStatsImpl(String filename) {
mFile = new JournaledFile(new File(filename), new File(filename + ".tmp"));
+ mHandler = new MyHandler();
mStartCount++;
- mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables);
+ mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables);
+ mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mUnpluggables);
}
mInputEventCounter = new Counter(mUnpluggables);
- mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables);
+ mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables);
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
- mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables);
+ mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null, mUnpluggables);
}
- mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables);
+ mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables);
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
- mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables);
+ mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables);
}
- mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables);
- mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables);
- mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables);
- mAudioOnTimer = new StopwatchTimer(-6, null, mUnpluggables);
- mVideoOnTimer = new StopwatchTimer(-7, null, mUnpluggables);
+ mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
+ mWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
+ mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
+ mAudioOnTimer = new StopwatchTimer(null, -6, null, mUnpluggables);
+ mVideoOnTimer = new StopwatchTimer(null, -7, null, mUnpluggables);
mOnBattery = mOnBatteryInternal = false;
initTimes();
mTrackBatteryPastUptime = 0;
@@ -3566,9 +3729,14 @@
public BatteryStatsImpl(Parcel p) {
mFile = null;
+ mHandler = null;
readFromParcel(p);
}
+ public void setCallback(BatteryCallback cb) {
+ mCallback = cb;
+ }
+
public void setNumSpeedSteps(int steps) {
if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
}
@@ -3653,6 +3821,9 @@
void setOnBattery(boolean onBattery, int oldStatus, int level) {
synchronized(this) {
boolean doWrite = false;
+ Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
+ m.arg1 = onBattery ? 1 : 0;
+ mHandler.sendMessage(m);
mOnBattery = mOnBatteryInternal = onBattery;
long uptime = SystemClock.uptimeMillis() * 1000;
@@ -4553,26 +4724,29 @@
mBatteryRealtime = in.readLong();
mBatteryLastRealtime = 0;
mScreenOn = false;
- mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in);
+ mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables, in);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in);
+ mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i,
+ null, mUnpluggables, in);
}
mInputEventCounter = new Counter(mUnpluggables, in);
mPhoneOn = false;
- mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
+ mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
- mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in);
+ mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
+ null, mUnpluggables, in);
}
- mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in);
+ mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables, in);
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
- mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in);
+ mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
+ null, mUnpluggables, in);
}
mWifiOn = false;
- mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
+ mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mWifiRunning = false;
- mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
+ mWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mBluetoothOn = false;
- mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
+ mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mUptime = in.readLong();
mUptimeStart = in.readLong();
mLastUptime = 0;
diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java
index 3a04993..1e97cd6 100644
--- a/core/java/com/android/internal/view/BaseSurfaceHolder.java
+++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java
@@ -41,7 +41,8 @@
int mRequestedWidth = -1;
int mRequestedHeight = -1;
- int mRequestedFormat = PixelFormat.OPAQUE;
+ /** @hide */
+ protected int mRequestedFormat = PixelFormat.OPAQUE;
int mRequestedType = -1;
long mLastLockTime = 0;
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index fe247e8..93fd54f 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -46,6 +46,7 @@
jfieldID mYPrecision;
jfieldID mEdgeFlags;
jfieldID mMetaState;
+ jfieldID mFlags;
jfieldID mNumPointers;
jfieldID mNumSamples;
jfieldID mPointerIdentifiers;
@@ -91,6 +92,8 @@
event->getEdgeFlags());
env->SetIntField(eventObj, gMotionEventClassInfo.mMetaState,
event->getMetaState());
+ env->SetIntField(eventObj, gMotionEventClassInfo.mFlags,
+ event->getFlags());
env->SetIntField(eventObj, gMotionEventClassInfo.mNumPointers,
numPointers);
env->SetIntField(eventObj, gMotionEventClassInfo.mNumSamples,
@@ -162,6 +165,7 @@
jfloat yPrecision = env->GetFloatField(eventObj, gMotionEventClassInfo.mYPrecision);
jint edgeFlags = env->GetIntField(eventObj, gMotionEventClassInfo.mEdgeFlags);
jint metaState = env->GetIntField(eventObj, gMotionEventClassInfo.mMetaState);
+ jint flags = env->GetIntField(eventObj, gMotionEventClassInfo.mFlags);
jint numPointers = env->GetIntField(eventObj, gMotionEventClassInfo.mNumPointers);
jint numSamples = env->GetIntField(eventObj, gMotionEventClassInfo.mNumSamples);
jintArray pointerIdentifierArray = jintArray(env->GetObjectField(eventObj,
@@ -196,7 +200,7 @@
samplePointerCoords[j].orientation = *(srcDataSamples++);
}
- event->initialize(deviceId, source, action, edgeFlags, metaState,
+ event->initialize(deviceId, source, action, flags, edgeFlags, metaState,
xOffset, yOffset, xPrecision, yPrecision, downTimeNano, sampleEventTime,
numPointers, pointerIdentifiers, samplePointerCoords);
@@ -281,6 +285,8 @@
"mEdgeFlags", "I");
GET_FIELD_ID(gMotionEventClassInfo.mMetaState, gMotionEventClassInfo.clazz,
"mMetaState", "I");
+ GET_FIELD_ID(gMotionEventClassInfo.mFlags, gMotionEventClassInfo.clazz,
+ "mFlags", "I");
GET_FIELD_ID(gMotionEventClassInfo.mNumPointers, gMotionEventClassInfo.clazz,
"mNumPointers", "I");
GET_FIELD_ID(gMotionEventClassInfo.mNumSamples, gMotionEventClassInfo.clazz,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0323b70..a9e49713 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -50,6 +50,8 @@
<protected-broadcast android:name="android.intent.action.ACTION_SHUTDOWN" />
<protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_LOW" />
<protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_OK" />
+ <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_FULL" />
+ <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_NOT_FULL" />
<protected-broadcast android:name="android.intent.action.NEW_OUTGOING_CALL" />
<protected-broadcast android:name="android.intent.action.REBOOT" />
<protected-broadcast android:name="android.intent.action.DOCK_EVENT" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 1130b69..13c3e7e 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1274,6 +1274,12 @@
be saved. -->
<attr name="saveEnabled" format="boolean" />
+ <!-- Specifies whether to filter touches when the view's window is obscured by
+ another visible window. When set to true, the view will not receive touches
+ whenever a toast, dialog or other window appears above the view's window.
+ Refer to the {@link android.view.View} security documentation for more details. -->
+ <attr name="filterTouchesWhenObscured" format="boolean" />
+
<!-- Defines the quality of translucent drawing caches. This property is used
only when the drawing cache is enabled and translucent. The default value is auto. -->
<attr name="drawingCacheQuality">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 86e79c8..28a7cca 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1254,6 +1254,7 @@
<public type="attr" name="overscrollMode" id="0x010102c1" />
<public type="attr" name="overscrollHeader" id="0x010102c2" />
<public type="attr" name="overscrollFooter" id="0x010102c3" />
+ <public type="attr" name="filterTouchesWhenObscured" id="0x010102c4" />
<public-padding type="attr" name="kraken_resource_pad" end="0x01010300" />
diff --git a/include/media/EffectEnvironmentalReverbApi.h b/include/media/EffectEnvironmentalReverbApi.h
index 2233e3f..36accd8 100644
--- a/include/media/EffectEnvironmentalReverbApi.h
+++ b/include/media/EffectEnvironmentalReverbApi.h
@@ -48,16 +48,16 @@
//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.
typedef struct s_reverb_settings {
- int16_t roomLevel;
- int16_t roomHFLevel;
- int32_t decayTime;
- int16_t decayHFRatio;
- int16_t reflectionsLevel;
- int32_t reflectionsDelay;
- int16_t reverbLevel;
- int32_t reverbDelay;
- int16_t diffusion;
- int16_t density;
+ int16_t roomLevel;
+ int16_t roomHFLevel;
+ uint32_t decayTime;
+ int16_t decayHFRatio;
+ int16_t reflectionsLevel;
+ uint32_t reflectionsDelay;
+ int16_t reverbLevel;
+ uint32_t reverbDelay;
+ int16_t diffusion;
+ int16_t density;
} __attribute__((packed)) t_reverb_settings;
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 3fa825f..b587e94 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -78,6 +78,11 @@
POLICY_FLAG_RAW_MASK = 0x0000ffff,
+ /* These flags are set by the input dispatcher. */
+
+ // Indicates that the input event was injected.
+ POLICY_FLAG_INJECTED = 0x01000000,
+
/* These flags are set by the input reader policy as it intercepts each event. */
// Indicates that the screen was off when the event was received and the event
@@ -225,6 +230,8 @@
inline int32_t getAction() const { return mAction; }
+ inline int32_t getFlags() const { return mFlags; }
+
inline int32_t getEdgeFlags() const { return mEdgeFlags; }
inline int32_t getMetaState() const { return mMetaState; }
@@ -343,6 +350,7 @@
int32_t deviceId,
int32_t source,
int32_t action,
+ int32_t flags,
int32_t edgeFlags,
int32_t metaState,
float xOffset,
@@ -370,6 +378,7 @@
private:
int32_t mAction;
+ int32_t mFlags;
int32_t mEdgeFlags;
int32_t mMetaState;
float mXOffset;
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index aed4fa1..f00f2db 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -84,14 +84,22 @@
* current event is delivered to this target or a timeout occurs. */
FLAG_SYNC = 0x01,
- /* This flag indicates that a MotionEvent with ACTION_DOWN falls outside of the area of
- * this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */
+ /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
+ * of the area of this target and so should instead be delivered as an
+ * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
FLAG_OUTSIDE = 0x02,
/* This flag indicates that a KeyEvent or MotionEvent is being canceled.
- * In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set.
- * In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */
- FLAG_CANCEL = 0x04
+ * In the case of a key event, it should be delivered with flag
+ * AKEY_EVENT_FLAG_CANCELED set.
+ * In the case of a motion event, it should be delivered with action
+ * AMOTION_EVENT_ACTION_CANCEL instead. */
+ FLAG_CANCEL = 0x04,
+
+ /* This flag indicates that the target of a MotionEvent is partly or wholly
+ * obscured by another visible window above it. The motion event should be
+ * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
+ FLAG_WINDOW_IS_OBSCURED = 0x08,
};
// The input channel to be targeted.
@@ -139,9 +147,12 @@
/* Notifies the system that an input channel recovered from ANR. */
virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0;
- /* Gets the key repeat timeout or -1 if automatic key repeating is disabled. */
+ /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
virtual nsecs_t getKeyRepeatTimeout() = 0;
+ /* Gets the key repeat inter-key delay. */
+ virtual nsecs_t getKeyRepeatDelay() = 0;
+
/* Waits for key event input targets to become available.
* If the event is being injected, injectorPid and injectorUid should specify the
* process id and used id of the injecting application, otherwise they should both
@@ -193,7 +204,8 @@
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
- uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+ uint32_t policyFlags, int32_t action, int32_t flags,
+ int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) = 0;
@@ -257,7 +269,8 @@
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime);
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
- uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+ uint32_t policyFlags, int32_t action, int32_t flags,
+ int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime);
@@ -327,6 +340,7 @@
int32_t source;
uint32_t policyFlags;
int32_t action;
+ int32_t flags;
int32_t metaState;
int32_t edgeFlags;
float xPrecision;
@@ -458,7 +472,8 @@
int32_t repeatCount, nsecs_t downTime);
MotionEntry* obtainMotionEntry(nsecs_t eventTime,
int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
- int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
+ int32_t flags, int32_t metaState, int32_t edgeFlags,
+ float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount,
const int32_t* pointerIds, const PointerCoords* pointerCoords);
DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 31ec701..82831e29 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -135,6 +135,7 @@
struct {
int32_t action;
+ int32_t flags;
int32_t metaState;
int32_t edgeFlags;
nsecs_t downTime;
@@ -218,6 +219,7 @@
int32_t deviceId,
int32_t source,
int32_t action,
+ int32_t flags,
int32_t edgeFlags,
int32_t metaState,
float xOffset,
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 4973cd8..811edaf 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -129,6 +129,7 @@
int32_t deviceId,
int32_t source,
int32_t action,
+ int32_t flags,
int32_t edgeFlags,
int32_t metaState,
float xOffset,
@@ -142,6 +143,7 @@
const PointerCoords* pointerCoords) {
InputEvent::initialize(deviceId, source);
mAction = action;
+ mFlags = flags;
mEdgeFlags = edgeFlags;
mMetaState = metaState;
mXOffset = xOffset;
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 886c785..df232d4 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -97,6 +97,7 @@
void InputDispatcher::dispatchOnce() {
nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
+ nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
bool skipPoll = false;
nsecs_t currentTime;
@@ -146,7 +147,7 @@
if (mInboundQueue.isEmpty()) {
if (mKeyRepeatState.lastKeyEntry) {
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
- processKeyRepeatLockedInterruptible(currentTime, keyRepeatTimeout);
+ processKeyRepeatLockedInterruptible(currentTime, keyRepeatDelay);
skipPoll = true;
} else {
if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
@@ -335,7 +336,7 @@
}
void InputDispatcher::processKeyRepeatLockedInterruptible(
- nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
+ nsecs_t currentTime, nsecs_t keyRepeatDelay) {
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
// Search the inbound queue for a key up corresponding to this device.
@@ -352,7 +353,7 @@
}
}
- // Synthesize a key repeat after the repeat timeout expired.
+ // Synthesize a key repeat.
// Reuse the repeated key entry if it is otherwise unreferenced.
uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
if (entry->refCount == 1) {
@@ -375,7 +376,7 @@
entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
}
- mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatTimeout;
+ mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
#if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
@@ -392,9 +393,11 @@
void InputDispatcher::processMotionLockedInterruptible(
nsecs_t currentTime, MotionEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
+ LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
+ "action=0x%x, flags=0x%x, "
"metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
- entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
+ entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
+ entry->action, entry->flags,
entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
entry->downTime);
@@ -406,7 +409,7 @@
}
for (uint32_t i = 0; i < entry->pointerCount; i++) {
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
- "touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
+ "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
"orientation=%f",
i, entry->pointerIds[i],
sample->pointerCoords[i].x, sample->pointerCoords[i].y,
@@ -465,7 +468,7 @@
mCurrentInputTargetsValid = false;
mLock.unlock();
- mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
+ mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
entry->edgeFlags, entry->metaState,
0, 0, entry->xPrecision, entry->yPrecision,
entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
@@ -698,12 +701,16 @@
// Apply target flags.
int32_t action = motionEntry->action;
+ int32_t flags = motionEntry->flags;
if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
action = AMOTION_EVENT_ACTION_OUTSIDE;
}
if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
action = AMOTION_EVENT_ACTION_CANCEL;
}
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
+ flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+ }
// If headMotionSample is non-NULL, then it points to the first new sample that we
// were unable to dispatch during the previous cycle so we resume dispatching from
@@ -726,7 +733,7 @@
// Publish the motion event and the first motion sample.
status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
- motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
+ motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
xOffset, yOffset,
motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, firstMotionSample->eventTime,
@@ -1073,18 +1080,18 @@
}
void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
- uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+ uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) {
#if DEBUG_INBOUND_EVENT_DETAILS
LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
- "downTime=%lld",
- eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
+ "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
+ "xPrecision=%f, yPrecision=%f, downTime=%lld",
+ eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
xPrecision, yPrecision, downTime);
for (uint32_t i = 0; i < pointerCount; i++) {
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
- "touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
+ "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
"orientation=%f",
i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
pointerCoords[i].pressure, pointerCoords[i].size,
@@ -1209,7 +1216,7 @@
// Just enqueue a new motion event.
MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
- deviceId, source, policyFlags, action, metaState, edgeFlags,
+ deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
xPrecision, yPrecision, downTime,
pointerCount, pointerIds, pointerCoords);
@@ -1359,7 +1366,7 @@
switch (event->getType()) {
case AINPUT_EVENT_TYPE_KEY: {
const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
- uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
+ uint32_t policyFlags = POLICY_FLAG_INJECTED;
KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
@@ -1371,7 +1378,7 @@
case AINPUT_EVENT_TYPE_MOTION: {
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
- uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
+ uint32_t policyFlags = POLICY_FLAG_INJECTED;
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
@@ -1379,7 +1386,8 @@
MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
- motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
+ motionEvent->getAction(), motionEvent->getFlags(),
+ motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
motionEvent->getDownTime(), uint32_t(pointerCount),
motionEvent->getPointerIds(), samplePointerCoords);
@@ -1664,7 +1672,7 @@
}
InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
- int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
+ int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount,
const int32_t* pointerIds, const PointerCoords* pointerCoords) {
@@ -1676,6 +1684,7 @@
entry->source = source;
entry->policyFlags = policyFlags;
entry->action = action;
+ entry->flags = flags;
entry->metaState = metaState;
entry->edgeFlags = edgeFlags;
entry->xPrecision = xPrecision;
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 8ffb48d..d57b38c 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -1153,7 +1153,7 @@
int32_t pointerId = 0;
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
- motionEventAction, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
}
@@ -2324,7 +2324,7 @@
} // release lock
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
- motionEventAction, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
+ motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
pointerCount, pointerIds, pointerCoords,
xPrecision, yPrecision, mDownTime);
}
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index cf0f63e..4c402dc 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -318,8 +318,8 @@
nsecs_t downTime,
nsecs_t eventTime) {
#if DEBUG_TRANSPORT_ACTIONS
- LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=%d, "
- "action=%d, flags=%d, keyCode=%d, scanCode=%d, metaState=%d, repeatCount=%d,"
+ LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, "
+ "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
"downTime=%lld, eventTime=%lld",
mChannel->getName().string(),
deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
@@ -346,6 +346,7 @@
int32_t deviceId,
int32_t source,
int32_t action,
+ int32_t flags,
int32_t edgeFlags,
int32_t metaState,
float xOffset,
@@ -358,12 +359,12 @@
const int32_t* pointerIds,
const PointerCoords* pointerCoords) {
#if DEBUG_TRANSPORT_ACTIONS
- LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=%d, "
- "action=%d, edgeFlags=%d, metaState=%d, xOffset=%f, yOffset=%f, "
+ LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
+ "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, "
"xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
"pointerCount=%d",
mChannel->getName().string(),
- deviceId, source, action, edgeFlags, metaState, xOffset, yOffset,
+ deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
xPrecision, yPrecision, downTime, eventTime, pointerCount);
#endif
@@ -379,6 +380,7 @@
}
mSharedMessage->motion.action = action;
+ mSharedMessage->motion.flags = flags;
mSharedMessage->motion.edgeFlags = edgeFlags;
mSharedMessage->motion.metaState = metaState;
mSharedMessage->motion.xOffset = xOffset;
@@ -664,6 +666,7 @@
mSharedMessage->deviceId,
mSharedMessage->source,
mSharedMessage->motion.action,
+ mSharedMessage->motion.flags,
mSharedMessage->motion.edgeFlags,
mSharedMessage->motion.metaState,
mSharedMessage->motion.xOffset,
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index 3bc21fa..952b974 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -138,6 +138,7 @@
const int32_t deviceId = 1;
const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
const int32_t action = AMOTION_EVENT_ACTION_MOVE;
+ const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
const float xOffset = -10;
@@ -167,7 +168,7 @@
}
}
- status = mPublisher->publishMotionEvent(deviceId, source, action, edgeFlags,
+ status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
metaState, xOffset, yOffset, xPrecision, yPrecision,
downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
ASSERT_EQ(OK, status)
@@ -213,6 +214,7 @@
EXPECT_EQ(deviceId, motionEvent->getDeviceId());
EXPECT_EQ(source, motionEvent->getSource());
EXPECT_EQ(action, motionEvent->getAction());
+ EXPECT_EQ(flags, motionEvent->getFlags());
EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
EXPECT_EQ(metaState, motionEvent->getMetaState());
EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
@@ -322,12 +324,12 @@
int32_t pointerIds[pointerCount] = { 0 };
PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(INVALID_OPERATION, status)
<< "publisher publishMotionEvent should return INVALID_OPERATION because ";
@@ -342,7 +344,7 @@
int32_t pointerIds[pointerCount];
PointerCoords pointerCoords[pointerCount];
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
@@ -356,7 +358,7 @@
int32_t pointerIds[pointerCount];
PointerCoords pointerCoords[pointerCount];
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
@@ -402,7 +404,7 @@
PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
- 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status);
status = mPublisher->appendMotionSample(0, pointerCoords);
@@ -419,7 +421,7 @@
PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
- 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status);
status = mPublisher->sendDispatchSignal();
@@ -446,7 +448,7 @@
PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
- 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status);
for (int count = 1;; count++) {
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 45ef416..b3e1531 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -1133,7 +1133,7 @@
//LOGV("\tReverbSetDecayTime() just Got -> %d\n", ActiveParams.T60);
if (time <= LVREV_MAX_T60) {
- ActiveParams.T60 = time;
+ ActiveParams.T60 = (LVM_UINT16)time;
}
else {
ActiveParams.T60 = LVREV_MAX_T60;
@@ -1146,7 +1146,7 @@
pContext->SamplesToExitCount = (ActiveParams.T60 * pContext->config.inputCfg.samplingRate)/1000;
//LOGV("\tReverbSetDecayTime() just Set SamplesToExitCount-> %d\n",pContext->SamplesToExitCount);
- pContext->SavedDecayTime = time;
+ pContext->SavedDecayTime = (int16_t)time;
//LOGV("\tReverbSetDecayTime end");
return;
}
@@ -1162,7 +1162,7 @@
//
//----------------------------------------------------------------------------
-int32_t ReverbGetDecayTime(ReverbContext *pContext){
+uint32_t ReverbGetDecayTime(ReverbContext *pContext){
//LOGV("\tReverbGetDecayTime start");
LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
@@ -1181,7 +1181,7 @@
}
//LOGV("\tReverbGetDecayTime end");
- return ActiveParams.T60;
+ return (uint32_t)ActiveParams.T60;
}
//----------------------------------------------------------------------------
@@ -1606,7 +1606,7 @@
// *(int16_t *)pValue);
break;
case REVERB_PARAM_DECAY_TIME:
- *(int32_t *)pValue = ReverbGetDecayTime(pContext);
+ *(uint32_t *)pValue = ReverbGetDecayTime(pContext);
//LOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_TIME Value is %d",
// *(int32_t *)pValue);
@@ -1671,6 +1671,7 @@
int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){
int status = 0;
int16_t level;
+ int16_t ratio;
uint32_t time;
t_reverb_settings *pProperties;
int32_t *pParamTemp = (int32_t *)pParam;
@@ -1688,6 +1689,7 @@
return -EINVAL;
}
pContext->nextPreset = preset;
+ return 0;
}
switch (param){
@@ -1724,10 +1726,10 @@
//LOGV("\tReverb_setParameter() Called ReverbSetDecayTime");
break;
case REVERB_PARAM_DECAY_HF_RATIO:
- time = *(int16_t *)pValue;
- //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_HF_RATIO value is %d", time);
+ ratio = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_HF_RATIO value is %d", ratio);
//LOGV("\tReverb_setParameter() Calling ReverbSetDecayHfRatio");
- ReverbSetDecayHfRatio(pContext, time);
+ ReverbSetDecayHfRatio(pContext, ratio);
//LOGV("\tReverb_setParameter() Called ReverbSetDecayHfRatio");
break;
case REVERB_PARAM_REVERB_LEVEL:
@@ -1738,17 +1740,17 @@
//LOGV("\tReverb_setParameter() Called ReverbSetReverbLevel");
break;
case REVERB_PARAM_DIFFUSION:
- time = *(int16_t *)pValue;
- //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DIFFUSION value is %d", time);
+ ratio = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DIFFUSION value is %d", ratio);
//LOGV("\tReverb_setParameter() Calling ReverbSetDiffusion");
- ReverbSetDiffusion(pContext, time);
+ ReverbSetDiffusion(pContext, ratio);
//LOGV("\tReverb_setParameter() Called ReverbSetDiffusion");
break;
case REVERB_PARAM_DENSITY:
- time = *(int16_t *)pValue;
- //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DENSITY value is %d", time);
+ ratio = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DENSITY value is %d", ratio);
//LOGV("\tReverb_setParameter() Calling ReverbSetDensity");
- ReverbSetDensity(pContext, time);
+ ReverbSetDensity(pContext, ratio);
//LOGV("\tReverb_setParameter() Called ReverbSetDensity");
break;
break;
diff --git a/native/android/input.cpp b/native/android/input.cpp
index c79f913..57f0072 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -84,6 +84,10 @@
return static_cast<const MotionEvent*>(motion_event)->getAction();
}
+int32_t AMotionEvent_getFlags(const AInputEvent* motion_event) {
+ return static_cast<const MotionEvent*>(motion_event)->getFlags();
+}
+
int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event) {
return static_cast<const MotionEvent*>(motion_event)->getMetaState();
}
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 5b62da4..9da122b 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -247,6 +247,22 @@
};
/*
+ * Motion event flags.
+ */
+enum {
+ /* This flag indicates that the window that received this motion event is partly
+ * or wholly obscured by another visible window above it. This flag is set to true
+ * even if the event did not directly pass through the obscured area.
+ * A security sensitive application can check this flag to identify situations in which
+ * a malicious application may have covered up part of its content for the purpose
+ * of misleading the user or hijacking touches. An appropriate response might be
+ * to drop the suspect touches or to take additional precautions to confirm the user's
+ * actual intent.
+ */
+ AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1,
+};
+
+/*
* Motion event edge touch flags.
*/
enum {
@@ -395,6 +411,9 @@
/* Get the combined motion event action code and pointer index. */
int32_t AMotionEvent_getAction(const AInputEvent* motion_event);
+/* Get the motion event flags. */
+int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
+
/* Get the state of any meta / modifier keys that were in effect when the
* event was generated. */
int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 3db5dc1..e454c08 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -668,7 +668,7 @@
while (true) {
String packageName = in.readUTF();
Slog.i(TAG, " + " + packageName);
- dataChanged(packageName);
+ dataChangedImpl(packageName);
}
} catch (EOFException e) {
// no more data; we're done
@@ -740,7 +740,7 @@
int uid = mBackupParticipants.keyAt(i);
HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
for (ApplicationInfo app: participants) {
- dataChanged(app.packageName);
+ dataChangedImpl(app.packageName);
}
}
}
@@ -896,7 +896,7 @@
if (!mEverStoredApps.contains(pkg.packageName)) {
if (DEBUG) Slog.i(TAG, "New app " + pkg.packageName
+ " never backed up; scheduling");
- dataChanged(pkg.packageName);
+ dataChangedImpl(pkg.packageName);
}
}
}
@@ -1327,7 +1327,7 @@
if (status != BackupConstants.TRANSPORT_OK) {
Slog.w(TAG, "Backup pass unsuccessful, restaging");
for (BackupRequest req : mQueue) {
- dataChanged(req.appInfo.packageName);
+ dataChangedImpl(req.appInfo.packageName);
}
// We also want to reset the backup schedule based on whatever
@@ -1997,25 +1997,66 @@
}
}
+ private void dataChangedImpl(String packageName) {
+ HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
+ dataChangedImpl(packageName, targets);
+ }
- // ----- IBackupManager binder interface -----
-
- public void dataChanged(String packageName) {
+ private void dataChangedImpl(String packageName, HashSet<ApplicationInfo> targets) {
// Record that we need a backup pass for the caller. Since multiple callers
// may share a uid, we need to note all candidates within that uid and schedule
// a backup pass for each of them.
EventLog.writeEvent(EventLogTags.BACKUP_DATA_CHANGED, packageName);
+ if (targets == null) {
+ Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
+ + " uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ synchronized (mQueueLock) {
+ // Note that this client has made data changes that need to be backed up
+ for (ApplicationInfo app : targets) {
+ // validate the caller-supplied package name against the known set of
+ // packages associated with this uid
+ if (app.packageName.equals(packageName)) {
+ // Add the caller to the set of pending backups. If there is
+ // one already there, then overwrite it, but no harm done.
+ BackupRequest req = new BackupRequest(app, false);
+ if (mPendingBackups.put(app, req) == null) {
+ // Journal this request in case of crash. The put()
+ // operation returned null when this package was not already
+ // in the set; we want to avoid touching the disk redundantly.
+ writeToJournalLocked(packageName);
+
+ if (DEBUG) {
+ int numKeys = mPendingBackups.size();
+ Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
+ for (BackupRequest b : mPendingBackups.values()) {
+ Slog.d(TAG, " + " + b + " agent=" + b.appInfo.backupAgentName);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Note: packageName is currently unused, but may be in the future
+ private HashSet<ApplicationInfo> dataChangedTargets(String packageName) {
// If the caller does not hold the BACKUP permission, it can only request a
// backup of its own data.
- HashSet<ApplicationInfo> targets;
if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
- targets = mBackupParticipants.get(Binder.getCallingUid());
- } else {
- // a caller with full permission can ask to back up any participating app
- // !!! TODO: allow backup of ANY app?
- targets = new HashSet<ApplicationInfo>();
+ synchronized (mBackupParticipants) {
+ return mBackupParticipants.get(Binder.getCallingUid());
+ }
+ }
+
+ // a caller with full permission can ask to back up any participating app
+ // !!! TODO: allow backup of ANY app?
+ HashSet<ApplicationInfo> targets = new HashSet<ApplicationInfo>();
+ synchronized (mBackupParticipants) {
int N = mBackupParticipants.size();
for (int i = 0; i < N; i++) {
HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
@@ -2024,37 +2065,7 @@
}
}
}
- if (targets != null) {
- synchronized (mQueueLock) {
- // Note that this client has made data changes that need to be backed up
- for (ApplicationInfo app : targets) {
- // validate the caller-supplied package name against the known set of
- // packages associated with this uid
- if (app.packageName.equals(packageName)) {
- // Add the caller to the set of pending backups. If there is
- // one already there, then overwrite it, but no harm done.
- BackupRequest req = new BackupRequest(app, false);
- if (mPendingBackups.put(app, req) == null) {
- // Journal this request in case of crash. The put()
- // operation returned null when this package was not already
- // in the set; we want to avoid touching the disk redundantly.
- writeToJournalLocked(packageName);
-
- if (DEBUG) {
- int numKeys = mPendingBackups.size();
- Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
- for (BackupRequest b : mPendingBackups.values()) {
- Slog.d(TAG, " + " + b + " agent=" + b.appInfo.backupAgentName);
- }
- }
- }
- }
- }
- }
- } else {
- Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
- + " uid=" + Binder.getCallingUid());
- }
+ return targets;
}
private void writeToJournalLocked(String str) {
@@ -2072,6 +2083,23 @@
}
}
+ // ----- IBackupManager binder interface -----
+
+ public void dataChanged(final String packageName) {
+ final HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
+ if (targets == null) {
+ Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
+ + " uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ mBackupHandler.post(new Runnable() {
+ public void run() {
+ dataChangedImpl(packageName, targets);
+ }
+ });
+ }
+
// Clear the given package's backup data from the current transport
public void clearBackupData(String packageName) {
if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName);
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 4a0df59..0b1a4a3 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -69,10 +69,12 @@
private static final int DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES = 12*60; //in minutes
private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB
private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000;
+ private static final int DEFAULT_FULL_THRESHOLD_BYTES = 1024*1024; // 1MB
private long mFreeMem; // on /data
private long mLastReportedFreeMem;
private long mLastReportedFreeMemTime;
private boolean mLowMemFlag=false;
+ private boolean mMemFullFlag=false;
private Context mContext;
private ContentResolver mContentResolver;
private long mTotalMemory; // on /data
@@ -87,9 +89,13 @@
private boolean mClearingCache;
private Intent mStorageLowIntent;
private Intent mStorageOkIntent;
+ private Intent mStorageFullIntent;
+ private Intent mStorageNotFullIntent;
private CachePackageDataObserver mClearCacheObserver;
private static final int _TRUE = 1;
private static final int _FALSE = 0;
+ private long mMemLowThreshold;
+ private int mMemFullThreshold;
/**
* This string is used for ServiceManager access to this class.
@@ -103,7 +109,7 @@
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- //dont handle an invalid message
+ //don't handle an invalid message
if (msg.what != DEVICE_MEMORY_WHAT) {
Slog.e(TAG, "Will not process invalid message");
return;
@@ -184,7 +190,7 @@
try {
if (localLOGV) Slog.i(TAG, "Clearing cache");
IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
- freeStorageAndNotify(getMemThreshold(), mClearCacheObserver);
+ freeStorageAndNotify(mMemLowThreshold, mClearCacheObserver);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
mClearingCache = false;
@@ -209,8 +215,7 @@
if (localLOGV) Slog.v(TAG, "freeMemory="+mFreeMem);
//post intent to NotificationManager to display icon if necessary
- long memThreshold = getMemThreshold();
- if (mFreeMem < memThreshold) {
+ if (mFreeMem < mMemLowThreshold) {
if (!mLowMemFlag) {
if (checkCache) {
// See if clearing cache helps
@@ -235,6 +240,17 @@
mLowMemFlag = false;
}
}
+ if (mFreeMem < mMemFullThreshold) {
+ if (!mMemFullFlag) {
+ sendFullNotification();
+ mMemFullFlag = true;
+ }
+ } else {
+ if (mMemFullFlag) {
+ cancelFullNotification();
+ mMemFullFlag = false;
+ }
+ }
}
if(localLOGV) Slog.i(TAG, "Posting Message again");
//keep posting messages to itself periodically
@@ -264,6 +280,20 @@
return mTotalMemory*value;
}
+ /*
+ * just query settings to retrieve the memory full threshold.
+ * Preferred this over using a ContentObserver since Settings.Secure caches the value
+ * any way
+ */
+ private int getMemFullThreshold() {
+ int value = Settings.Secure.getInt(
+ mContentResolver,
+ Settings.Secure.SYS_STORAGE_FULL_THRESHOLD_BYTES,
+ DEFAULT_FULL_THRESHOLD_BYTES);
+ if(localLOGV) Slog.v(TAG, "Full Threshold Bytes="+value);
+ return value;
+ }
+
/**
* Constructor to run service. initializes the disk space threshold value
* and posts an empty message to kickstart the process.
@@ -283,6 +313,13 @@
mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL);
+ mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
+ mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ // cache storage thresholds
+ mMemLowThreshold = getMemThreshold();
+ mMemFullThreshold = getMemFullThreshold();
checkMemory(true);
}
@@ -332,6 +369,23 @@
mContext.sendBroadcast(mStorageOkIntent);
}
+ /**
+ * Send a notification when storage is full.
+ */
+ private final void sendFullNotification() {
+ if(localLOGV) Slog.i(TAG, "Sending memory full notification");
+ mContext.sendStickyBroadcast(mStorageFullIntent);
+ }
+
+ /**
+ * Cancels memory full notification and sends "not full" intent.
+ */
+ private final void cancelFullNotification() {
+ if(localLOGV) Slog.i(TAG, "Canceling memory full notification");
+ mContext.removeStickyBroadcast(mStorageFullIntent);
+ mContext.sendBroadcast(mStorageNotFullIntent);
+ }
+
public void updateMemory() {
int callingUid = getCallingUid();
if(callingUid != Process.SYSTEM_UID) {
diff --git a/services/java/com/android/server/InputWindow.java b/services/java/com/android/server/InputWindow.java
index 8da0cf1..dbc59ef 100644
--- a/services/java/com/android/server/InputWindow.java
+++ b/services/java/com/android/server/InputWindow.java
@@ -34,9 +34,17 @@
// Dispatching timeout.
public long dispatchingTimeoutNanos;
- // Window frame position.
+ // 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;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3841f75..0bc9b61 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5218,6 +5218,14 @@
final Rect frame = child.mFrame;
inputWindow.frameLeft = frame.left;
inputWindow.frameTop = frame.top;
+ inputWindow.frameRight = frame.right;
+ inputWindow.frameBottom = frame.bottom;
+
+ final Rect visibleFrame = child.mVisibleFrame;
+ inputWindow.visibleFrameLeft = visibleFrame.left;
+ inputWindow.visibleFrameTop = visibleFrame.top;
+ inputWindow.visibleFrameRight = visibleFrame.right;
+ inputWindow.visibleFrameBottom = visibleFrame.bottom;
switch (child.mTouchableInsets) {
default:
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 89a1627..3142ee4 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -131,7 +131,8 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
-public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
+public final class ActivityManagerService extends ActivityManagerNative
+ implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
static final String TAG = "ActivityManager";
static final boolean DEBUG = false;
static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
@@ -750,6 +751,7 @@
boolean mBooting = false;
boolean mWaitingUpdate = false;
boolean mDidUpdate = false;
+ boolean mOnBattery = false;
Context mContext;
@@ -1381,8 +1383,10 @@
systemDir, "batterystats.bin").toString());
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.getActiveStatistics().writeLocked();
+ mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
+ mBatteryStatsService.getActiveStatistics().setCallback(this);
- mUsageStatsService = new UsageStatsService( new File(
+ mUsageStatsService = new UsageStatsService(new File(
systemDir, "usagestats").toString());
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
@@ -1495,25 +1499,36 @@
synchronized(bstats) {
synchronized(mPidsSelfLocked) {
if (haveNewCpuStats) {
- if (mBatteryStatsService.isOnBattery()) {
+ if (mOnBattery) {
+ int perc = bstats.startAddingCpuLocked();
+ int totalUTime = 0;
+ int totalSTime = 0;
final int N = mProcessStats.countWorkingStats();
for (int i=0; i<N; i++) {
ProcessStats.Stats st
= mProcessStats.getWorkingStats(i);
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
+ int otherUTime = (st.rel_utime*perc)/100;
+ int otherSTime = (st.rel_stime*perc)/100;
+ totalUTime += otherUTime;
+ totalSTime += otherSTime;
if (pr != null) {
BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
- ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+ ps.addCpuTimeLocked(st.rel_utime-otherUTime,
+ st.rel_stime-otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
} else {
BatteryStatsImpl.Uid.Proc ps =
bstats.getProcessStatsLocked(st.name, st.pid);
if (ps != null) {
- ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+ ps.addCpuTimeLocked(st.rel_utime-otherUTime,
+ st.rel_stime-otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
}
}
}
+ bstats.finishAddingCpuLocked(perc, totalUTime,
+ totalSTime, cpuSpeedTimes);
}
}
}
@@ -1526,6 +1541,23 @@
}
}
+ @Override
+ public void batteryNeedsCpuUpdate() {
+ updateCpuStatsNow();
+ }
+
+ @Override
+ public void batteryPowerChanged(boolean onBattery) {
+ // When plugging in, update the CPU stats first before changing
+ // the plug state.
+ updateCpuStatsNow();
+ synchronized (this) {
+ synchronized(mPidsSelfLocked) {
+ mOnBattery = onBattery;
+ }
+ }
+ }
+
/**
* Initialize the application bind args. These are passed to each
* process when the bindApplication() IPC is sent to the process. They're
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 6d1fbab..67df707 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -131,6 +131,13 @@
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
+ long wtime;
+ synchronized (batteryStats.getBatteryStats()) {
+ wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid,
+ pid, SystemClock.elapsedRealtime());
+ }
+ long timeUsed = wtime - lastWakeTime;
+
if (info.className != null) {
pw.print(prefix); pw.print("class="); pw.println(info.className);
}
@@ -182,7 +189,9 @@
pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
pw.print(" lruSeq="); pw.println(lruSeq);
pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
- pw.print(" lastRequestedGc=");
+ pw.print(" time used=");
+ TimeUtils.formatDuration(timeUsed, pw); pw.println("");
+ pw.print(prefix); pw.print("lastRequestedGc=");
TimeUtils.formatDuration(lastRequestedGc, now, pw);
pw.print(" lastLowMemory=");
TimeUtils.formatDuration(lastLowMemory, now, pw);
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index a237ee9..7af5e95 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -169,6 +169,12 @@
jfieldID dispatchingTimeoutNanos;
jfieldID frameLeft;
jfieldID frameTop;
+ jfieldID frameRight;
+ jfieldID frameBottom;
+ jfieldID visibleFrameLeft;
+ jfieldID visibleFrameTop;
+ jfieldID visibleFrameRight;
+ jfieldID visibleFrameBottom;
jfieldID touchableAreaLeft;
jfieldID touchableAreaTop;
jfieldID touchableAreaRight;
@@ -269,6 +275,7 @@
nsecs_t& outNewTimeout);
virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel);
virtual nsecs_t getKeyRepeatTimeout();
+ virtual nsecs_t getKeyRepeatDelay();
virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
@@ -283,6 +290,12 @@
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;
@@ -294,10 +307,8 @@
int32_t ownerPid;
int32_t ownerUid;
- inline bool touchableAreaContainsPoint(int32_t x, int32_t y) {
- return x >= touchableAreaLeft && x <= touchableAreaRight
- && y >= touchableAreaTop && y <= touchableAreaBottom;
- }
+ bool visibleFrameIntersects(const InputWindow* other) const;
+ bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
};
struct InputApplication {
@@ -370,9 +381,13 @@
// Focus tracking for touch.
bool mTouchDown;
InputWindow* mTouchedWindow; // primary target for current down
+ bool mTouchedWindowIsObscured; // true if other windows may obscure the target
Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
-
- Vector<InputWindow*> mTempTouchedOutsideWindows; // temporary outside touch targets
+ struct OutsideTarget {
+ InputWindow* window;
+ bool obscured;
+ };
+ Vector<OutsideTarget> mTempTouchedOutsideTargets; // temporary outside touch targets
Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
// Focused application.
@@ -391,6 +406,7 @@
int32_t waitForTouchedWindowLd(MotionEvent* motionEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid,
Vector<InputTarget>& outTargets, InputWindow*& outTouchedWindow);
+ bool isWindowObscuredLocked(const InputWindow* window);
void releaseTouchedWindowLd();
@@ -996,6 +1012,10 @@
}
}
+nsecs_t NativeInputManager::getKeyRepeatDelay() {
+ return milliseconds_to_nanoseconds(50);
+}
+
int32_t NativeInputManager::getMaxEventsPerSecond() {
if (mMaxEventsPerSecond < 0) {
JNIEnv* env = jniEnv();
@@ -1117,6 +1137,18 @@
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,
@@ -1144,6 +1176,12 @@
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;
@@ -1417,11 +1455,12 @@
/* Case 1: ACTION_DOWN */
InputWindow* newTouchedWindow = NULL;
- mTempTouchedOutsideWindows.clear();
+ mTempTouchedOutsideTargets.clear();
int32_t x = int32_t(motionEvent->getX(0));
int32_t y = int32_t(motionEvent->getY(0));
InputWindow* topErrorWindow = NULL;
+ bool obscured = false;
// Traverse windows from front to back to find touched window and outside targets.
size_t numWindows = mWindows.size();
@@ -1442,13 +1481,17 @@
if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
if (! screenWasOff || flags & FLAG_TOUCHABLE_WHEN_WAKING) {
newTouchedWindow = window;
+ obscured = isWindowObscuredLocked(window);
}
break; // found touched window, exit window loop
}
}
if (flags & FLAG_WATCH_OUTSIDE_TOUCH) {
- mTempTouchedOutsideWindows.push(window);
+ OutsideTarget outsideTarget;
+ outsideTarget.window = window;
+ outsideTarget.obscured = isWindowObscuredLocked(window);
+ mTempTouchedOutsideTargets.push(outsideTarget);
}
}
}
@@ -1501,6 +1544,7 @@
releaseTouchedWindowLd();
mTouchedWindow = newTouchedWindow;
+ mTouchedWindowIsObscured = obscured;
if (newTouchedWindow->hasWallpaper) {
mTouchedWallpaperWindows.appendVector(mWallpaperWindows);
@@ -1557,21 +1601,31 @@
if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
size_t numWallpaperWindows = mTouchedWallpaperWindows.size();
for (size_t i = 0; i < numWallpaperWindows; i++) {
- addTarget(mTouchedWallpaperWindows[i], 0, 0, outTargets);
+ addTarget(mTouchedWallpaperWindows[i],
+ InputTarget::FLAG_WINDOW_IS_OBSCURED, 0, outTargets);
}
- size_t numOutsideWindows = mTempTouchedOutsideWindows.size();
- for (size_t i = 0; i < numOutsideWindows; i++) {
- addTarget(mTempTouchedOutsideWindows[i], InputTarget::FLAG_OUTSIDE, 0, outTargets);
+ size_t numOutsideTargets = mTempTouchedOutsideTargets.size();
+ for (size_t i = 0; i < numOutsideTargets; i++) {
+ const OutsideTarget& outsideTarget = mTempTouchedOutsideTargets[i];
+ int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
+ if (outsideTarget.obscured) {
+ outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+ }
+ addTarget(outsideTarget.window, outsideTargetFlags, 0, outTargets);
}
- addTarget(mTouchedWindow, InputTarget::FLAG_SYNC,
+ int32_t targetFlags = InputTarget::FLAG_SYNC;
+ if (mTouchedWindowIsObscured) {
+ targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+ }
+ addTarget(mTouchedWindow, targetFlags,
anrTimer.getTimeSpentWaitingForApplication(), outTargets);
outTouchedWindow = mTouchedWindow;
} else {
outTouchedWindow = NULL;
}
- mTempTouchedOutsideWindows.clear();
+ mTempTouchedOutsideTargets.clear();
// Check injection permission once and for all.
if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
@@ -1616,6 +1670,7 @@
void NativeInputManager::releaseTouchedWindowLd() {
mTouchedWindow = NULL;
+ mTouchedWindowIsObscured = false;
mTouchedWallpaperWindows.clear();
}
@@ -1661,6 +1716,20 @@
return true;
}
+bool NativeInputManager::isWindowObscuredLocked(const InputWindow* window) {
+ size_t numWindows = mWindows.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const InputWindow* other = & mWindows.itemAt(i);
+ if (other == window) {
+ break;
+ }
+ if (other->visible && window->visibleFrameIntersects(other)) {
+ return true;
+ }
+ }
+ return false;
+}
+
int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) {
#if DEBUG_INPUT_DISPATCHER_POLICY
@@ -1935,12 +2004,17 @@
for (size_t i = 0; i < mWindows.size(); i++) {
dump.appendFormat(" windows[%d]: '%s', paused=%d, hasFocus=%d, hasWallpaper=%d, "
"visible=%d, flags=0x%08x, type=0x%08x, "
- "frame=[%d,%d], touchableArea=[%d,%d][%d,%d], "
+ "frame=[%d,%d][%d,%d], "
+ "visibleFrame=[%d,%d][%d,%d], "
+ "touchableArea=[%d,%d][%d,%d], "
"ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
i, mWindows[i].inputChannel->getName().string(),
mWindows[i].paused, mWindows[i].hasFocus, mWindows[i].hasWallpaper,
mWindows[i].visible, mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
mWindows[i].frameLeft, mWindows[i].frameTop,
+ mWindows[i].frameRight, mWindows[i].frameBottom,
+ mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
+ mWindows[i].visibleFrameRight, mWindows[i].visibleFrameBottom,
mWindows[i].touchableAreaLeft, mWindows[i].touchableAreaTop,
mWindows[i].touchableAreaRight, mWindows[i].touchableAreaBottom,
mWindows[i].ownerPid, mWindows[i].ownerUid,
@@ -1955,6 +2029,20 @@
// ----------------------------------------------------------------------------
+bool NativeInputManager::InputWindow::visibleFrameIntersects(const InputWindow* other) const {
+ return visibleFrameRight > other->visibleFrameLeft
+ && visibleFrameLeft < other->visibleFrameRight
+ && visibleFrameBottom > other->visibleFrameTop
+ && visibleFrameTop < other->visibleFrameBottom;
+}
+
+bool NativeInputManager::InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
+ return x >= touchableAreaLeft && x <= touchableAreaRight
+ && y >= touchableAreaTop && y <= touchableAreaBottom;
+}
+
+// ----------------------------------------------------------------------------
+
NativeInputManager::ANRTimer::ANRTimer() :
mBudget(APPLICATION), mStartTime(now()), mFrozen(false), mPausedWindow(NULL) {
}
@@ -2507,6 +2595,24 @@
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");
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index c1232e8..caec7e1 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -466,6 +466,33 @@
}
/**
+ * Hangup foreground call and resume the specific background call
+ *
+ * Note: this is noop if there is no foreground call or the heldCall is null
+ *
+ * @param heldCall to become foreground
+ * @throws CallStateException
+ */
+ public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException {
+ Phone foregroundPhone = null;
+ Phone backgroundPhone = null;
+
+ if (hasActiveFgCall()) {
+ foregroundPhone = getFgPhone();
+ if (heldCall != null) {
+ backgroundPhone = heldCall.getPhone();
+ if (foregroundPhone == backgroundPhone) {
+ getActiveFgCall().hangup();
+ } else {
+ // the call to be hangup and resumed belongs to different phones
+ getActiveFgCall().hangup();
+ switchHoldingAndActive(heldCall);
+ }
+ }
+ }
+ }
+
+ /**
* Whether or not the phone can conference in the current phone
* state--that is, one call holding and one call active.
* @return true if the phone can conference; false otherwise.
diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 8a5a6ae..5fef6de 100644
--- a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -57,7 +57,7 @@
* @param destPort the port to deliver the message to
* @param data the body of the message to send
* @param sentIntent if not NULL this <code>PendingIntent</code> is
- * broadcast when the message is sucessfully sent, or failed.
+ * broadcast when the message is successfully sent, or failed.
* The result code will be <code>Activity.RESULT_OK<code> for success,
* or one of these errors:<br>
* <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
@@ -67,7 +67,7 @@
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.<br>
* The per-application based SMS control checks sentIntent. If sentIntent
- * is NULL the caller will be checked against all unknown applicaitons,
+ * is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is delivered to the recipient. The
@@ -94,7 +94,7 @@
* the current default SMSC
* @param text the body of the message to send
* @param sentIntent if not NULL this <code>PendingIntent</code> is
- * broadcast when the message is sucessfully sent, or failed.
+ * broadcast when the message is successfully sent, or failed.
* The result code will be <code>Activity.RESULT_OK<code> for success,
* or one of these errors:<br>
* <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
@@ -140,7 +140,7 @@
* <code>RESULT_ERROR_RADIO_OFF</code>
* <code>RESULT_ERROR_NULL_PDU</code>.
* The per-application based SMS control checks sentIntent. If sentIntent
- * is NULL the caller will be checked against all unknown applicaitons,
+ * is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntents if not null, an <code>ArrayList</code> of
* <code>PendingIntent</code>s (one for each message part) that is
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index 606b52d..917e1d8 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -32,9 +32,11 @@
import android.database.SQLException;
import android.net.Uri;
import android.os.AsyncResult;
+import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
+import android.os.StatFs;
import android.provider.Telephony;
import android.provider.Telephony.Sms.Intents;
import android.provider.Settings;
@@ -240,11 +242,9 @@
// Register for device storage intents. Use these to notify the RIL
// that storage for SMS is or is not available.
- // TODO: Revisit this for a later release. Storage reporting should
- // rely more on application indication.
IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
- filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
+ filter.addAction(Intent.ACTION_DEVICE_STORAGE_FULL);
+ filter.addAction(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
mContext.registerReceiver(mResultReceiver, filter);
}
@@ -679,7 +679,7 @@
* the extra "errorCode" containing a radio technology specific value,
* generally only useful for troubleshooting.<br>
* The per-application based SMS control checks sentIntent. If sentIntent
- * is NULL the caller will be checked against all unknown applicaitons,
+ * is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is delivered to the recipient. The
@@ -732,7 +732,7 @@
* <code>RESULT_ERROR_RADIO_OFF</code>
* <code>RESULT_ERROR_NULL_PDU</code>.
* The per-application based SMS control checks sentIntent. If sentIntent
- * is NULL the caller will be checked against all unknown applicaitons,
+ * is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntents if not null, an <code>ArrayList</code> of
* <code>PendingIntent</code>s (one for each message part) that is
@@ -748,7 +748,7 @@
* Send a SMS
*
* @param smsc the SMSC to send the message through, or NULL for the
- * defatult SMSC
+ * default SMSC
* @param pdu the raw PDU to send
* @param sentIntent if not NULL this <code>Intent</code> is
* broadcast when the message is successfully sent, or failed.
@@ -758,7 +758,7 @@
* <code>RESULT_ERROR_RADIO_OFF</code>
* <code>RESULT_ERROR_NULL_PDU</code>.
* The per-application based SMS control checks sentIntent. If sentIntent
- * is NULL the caller will be checked against all unknown applicaitons,
+ * is NULL the caller will be checked against all unknown applications,
* which cause smaller number of SMS to be sent in checking period.
* @param deliveryIntent if not NULL this <code>Intent</code> is
* broadcast when the message is delivered to the recipient. The
@@ -965,10 +965,10 @@
private BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_LOW)) {
+ if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_FULL)) {
mStorageAvailable = false;
mCm.reportSmsMemoryStatus(false, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
- } else if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_OK)) {
+ } else if (intent.getAction().equals(Intent.ACTION_DEVICE_STORAGE_NOT_FULL)) {
mStorageAvailable = true;
mCm.reportSmsMemoryStatus(true, obtainMessage(EVENT_REPORT_MEMORY_STATUS_DONE));
} else {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 4508e9a..f48c956 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -100,7 +100,6 @@
CdmaCallTracker mCT;
CdmaSMSDispatcher mSMS;
CdmaServiceStateTracker mSST;
- RuimFileHandler mRuimFileHandler;
RuimRecords mRuimRecords;
RuimCard mRuimCard;
ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>();
@@ -158,7 +157,7 @@
mDataConnection = new CdmaDataConnectionTracker (this);
mRuimCard = new RuimCard(this);
mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
- mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this);
+ mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
index cfcfd98..e97549d 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
@@ -27,6 +27,7 @@
import com.android.internal.telephony.IccSmsInterfaceManager;
import com.android.internal.telephony.IccUtils;
import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsRawData;
import java.util.ArrayList;
@@ -81,9 +82,9 @@
}
};
- public RuimSmsInterfaceManager(CDMAPhone phone) {
+ public RuimSmsInterfaceManager(CDMAPhone phone, SMSDispatcher dispatcher) {
super(phone);
- mDispatcher = new CdmaSMSDispatcher(phone);
+ mDispatcher = dispatcher;
}
public void dispose() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index e5ca519..689a972 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -117,10 +117,6 @@
Thread debugPortThread;
ServerSocket debugSocket;
- private int mReportedRadioResets;
- private int mReportedAttemptedConnects;
- private int mReportedSuccessfulConnects;
-
private String mImei;
private String mImeiSv;
private String mVmNumber;
@@ -151,7 +147,7 @@
mSimCard = new SimCard(this);
if (!unitTestMode) {
mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
- mSimSmsIntManager = new SimSmsInterfaceManager(this);
+ mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
}
mStkService = StkService.getInstance(mCM, mSIMRecords, mContext,
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
index 2028ca4..67ecc77 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
@@ -25,6 +25,7 @@
import com.android.internal.telephony.IccConstants;
import com.android.internal.telephony.IccSmsInterfaceManager;
import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.SMSDispatcher;
import com.android.internal.telephony.SmsRawData;
import java.util.ArrayList;
@@ -78,9 +79,9 @@
}
};
- public SimSmsInterfaceManager(GSMPhone phone) {
+ public SimSmsInterfaceManager(GSMPhone phone, SMSDispatcher dispatcher) {
super(phone);
- mDispatcher = new GsmSMSDispatcher(phone);
+ mDispatcher = dispatcher;
}
public void dispose() {