diff options
45 files changed, 1178 insertions, 259 deletions
diff --git a/api/current.xml b/api/current.xml index e938246449e4..a495d047eb0e 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 2acc4a05792a..7154aeee08d4 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1567,6 +1567,30 @@ public class Intent implements Parcelable, Cloneable { @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 a857e582beaf..32fb108c593c 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1586,8 +1586,10 @@ public abstract class BatteryStats implements Parcelable { 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 d20e89dcae1b..075da338cb39 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -75,6 +75,22 @@ public final class MediaStore { 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 78a384b65317..7c80420e1a83 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2961,31 +2961,31 @@ public final class Settings { 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 @@ public final class Settings { "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 57a72bf75bd9..2b083dca2ca6 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -30,6 +30,7 @@ import android.content.Context; 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 @@ public abstract class WallpaperService extends Service { }; 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 dde0889a5e8b..4e2c3c395ce7 100644 --- a/core/java/android/text/format/DateUtils.java +++ b/core/java/android/text/format/DateUtils.java @@ -168,6 +168,12 @@ public class DateUtils 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 @@ public class DateUtils * {@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 @@ public class DateUtils /** * 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 @@ public class DateUtils * 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 @@ public class DateUtils * @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 @@ public class DateUtils // 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 @@ public class DateUtils 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 5be2a4866c4f..09cbbb8069da 100644 --- a/core/java/android/text/method/TextKeyListener.java +++ b/core/java/android/text/method/TextKeyListener.java @@ -246,8 +246,10 @@ public class TextKeyListener extends BaseKeyListener implements SpanWatcher { 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 74318ba28cc2..78b9b5d8a84a 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -30,6 +30,7 @@ import android.os.SystemClock; */ 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 @@ public final class MotionEvent extends InputEvent implements Parcelable { @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 @@ public final class MotionEvent extends InputEvent implements Parcelable { private float mYPrecision; private int mEdgeFlags; private int mMetaState; + private int mFlags; private int mNumPointers; private int mNumSamples; @@ -338,20 +350,22 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @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 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @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 @@ public final class MotionEvent extends InputEvent implements Parcelable { 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 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @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 @@ public final class MotionEvent extends InputEvent implements Parcelable { 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 @@ public final class MotionEvent extends InputEvent implements Parcelable { 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 @@ public final class MotionEvent extends InputEvent implements Parcelable { } /** + * 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 @@ public final class MotionEvent extends InputEvent implements Parcelable { /** - * 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 @@ public final class MotionEvent extends InputEvent implements Parcelable { 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 @@ public final class MotionEvent extends InputEvent implements Parcelable { 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 7332c16d15f9..fe003a4ece6f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -542,6 +542,28 @@ import java.util.WeakHashMap; * 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 @@ import java.util.WeakHashMap; * @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 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility */ 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 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility 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 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility 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 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * @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 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** + * 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 715992912368..28bed3a0d489 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -822,6 +822,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ @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 659f9cd673c6..76701a937886 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -74,6 +74,8 @@ public interface WindowManagerPolicy { 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 d0dd6cc751e1..3428206470b0 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5817,7 +5817,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } - if (mText.length() > 0 && getSelectionStart() >= 0) { + if (mText.length() > 0 && hasSelection()) { return true; } @@ -7140,6 +7143,49 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 566ed29d15c7..b73b78ba8960 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.bluetooth.BluetoothHeadset; 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { // For debugging public BatteryStatsImpl() { mFile = null; + mHandler = null; } public static interface Unpluggable { @@ -739,7 +777,9 @@ public final class BatteryStatsImpl extends BatteryStats { * 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { } } 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 final class BatteryStatsImpl extends BatteryStats { 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); + 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); - mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables); - mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables); } @Override @@ -1996,7 +2155,7 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { return null; } - return new StopwatchTimer(type, pool, unpluggables, in); + return new StopwatchTimer(Uid.this, type, pool, unpluggables, in); } boolean reset() { @@ -2614,7 +2773,7 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 final class BatteryStatsImpl extends BatteryStats { 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 final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 @@ public final class BatteryStatsImpl extends BatteryStats { 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 3a0499359f57..1e97cd687f40 100644 --- a/core/java/com/android/internal/view/BaseSurfaceHolder.java +++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java @@ -41,7 +41,8 @@ public abstract class BaseSurfaceHolder implements SurfaceHolder { 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 fe247e87f096..93fd54feddda 100644 --- a/core/jni/android_view_MotionEvent.cpp +++ b/core/jni/android_view_MotionEvent.cpp @@ -46,6 +46,7 @@ static struct { jfieldID mYPrecision; jfieldID mEdgeFlags; jfieldID mMetaState; + jfieldID mFlags; jfieldID mNumPointers; jfieldID mNumSamples; jfieldID mPointerIdentifiers; @@ -91,6 +92,8 @@ jobject android_view_MotionEvent_fromNative(JNIEnv* env, const MotionEvent* even 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 @@ void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, 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 @@ void android_view_MotionEvent_toNative(JNIEnv* env, jobject eventObj, 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 @@ int register_android_view_MotionEvent(JNIEnv* env) { "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 0323b7044b53..a9e4971348dc 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 1130b6909448..13c3e7eacab9 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 86e79c809d02..28a7cca1adc1 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 2233e3fbdf75..36accd847ac2 100644 --- a/include/media/EffectEnvironmentalReverbApi.h +++ b/include/media/EffectEnvironmentalReverbApi.h @@ -48,16 +48,16 @@ typedef enum //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 3fa825f9bf42..b587e94db570 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -78,6 +78,11 @@ enum { 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 @@ public: 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 @@ public: int32_t deviceId, int32_t source, int32_t action, + int32_t flags, int32_t edgeFlags, int32_t metaState, float xOffset, @@ -370,6 +378,7 @@ public: 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 aed4fa112b14..f00f2dbce3ff 100644 --- a/include/ui/InputDispatcher.h +++ b/include/ui/InputDispatcher.h @@ -84,14 +84,22 @@ struct InputTarget { * 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 @@ public: /* 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 @@ public: 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 @@ public: 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 @@ private: int32_t source; uint32_t policyFlags; int32_t action; + int32_t flags; int32_t metaState; int32_t edgeFlags; float xPrecision; @@ -458,7 +472,8 @@ private: 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 31ec7019a624..82831e29b6fc 100644 --- a/include/ui/InputTransport.h +++ b/include/ui/InputTransport.h @@ -135,6 +135,7 @@ struct InputMessage { struct { int32_t action; + int32_t flags; int32_t metaState; int32_t edgeFlags; nsecs_t downTime; @@ -218,6 +219,7 @@ public: 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 4973cd89f226..811edaf8a26f 100644 --- a/libs/ui/Input.cpp +++ b/libs/ui/Input.cpp @@ -129,6 +129,7 @@ void MotionEvent::initialize( int32_t deviceId, int32_t source, int32_t action, + int32_t flags, int32_t edgeFlags, int32_t metaState, float xOffset, @@ -142,6 +143,7 @@ void MotionEvent::initialize( 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 886c7856debb..df232d425bd3 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -97,6 +97,7 @@ InputDispatcher::~InputDispatcher() { void InputDispatcher::dispatchOnce() { nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout(); + nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay(); bool skipPoll = false; nsecs_t currentTime; @@ -146,7 +147,7 @@ void InputDispatcher::dispatchOnce() { 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::processKeyLockedInterruptible( } 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 @@ void InputDispatcher::processKeyRepeatLockedInterruptible( } } - // 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 @@ void InputDispatcher::processKeyRepeatLockedInterruptible( 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::processKeyRepeatLockedInterruptible( 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 @@ void InputDispatcher::processMotionLockedInterruptible( } 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 @@ void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible( 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 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, // 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 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, // 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::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou } 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 @@ NoBatchingOrStreaming:; // 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 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked( 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 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked( 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 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked( 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::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t ev } 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 @@ InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsec 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 8ffb48debe8f..d57b38c2e2f7 100644 --- a/libs/ui/InputReader.cpp +++ b/libs/ui/InputReader.cpp @@ -1153,7 +1153,7 @@ void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEv 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 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags, } // 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 cf0f63e247a1..4c402dc0202e 100644 --- a/libs/ui/InputTransport.cpp +++ b/libs/ui/InputTransport.cpp @@ -318,8 +318,8 @@ status_t InputPublisher::publishKeyEvent( 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 @@ status_t InputPublisher::publishMotionEvent( int32_t deviceId, int32_t source, int32_t action, + int32_t flags, int32_t edgeFlags, int32_t metaState, float xOffset, @@ -358,12 +359,12 @@ status_t InputPublisher::publishMotionEvent( 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 @@ status_t InputPublisher::publishMotionEvent( } mSharedMessage->motion.action = action; + mSharedMessage->motion.flags = flags; mSharedMessage->motion.edgeFlags = edgeFlags; mSharedMessage->motion.metaState = metaState; mSharedMessage->motion.xOffset = xOffset; @@ -664,6 +666,7 @@ void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const { 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 3bc21fa29656..952b9747691e 100644 --- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp @@ -138,6 +138,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent( 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 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent( } } - 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 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent( 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 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsErr 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 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessTha 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 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreater 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 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenPublishedMotionEven 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 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenAlreadyConsumed_Ret 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 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenBufferFull_ReturnsE 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 45ef416fc712..b3e153122ca9 100755 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -1133,7 +1133,7 @@ void ReverbSetDecayTime(ReverbContext *pContext, uint32_t time){ //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 @@ void ReverbSetDecayTime(ReverbContext *pContext, uint32_t time){ 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 @@ void ReverbSetDecayTime(ReverbContext *pContext, uint32_t time){ // //---------------------------------------------------------------------------- -int32_t ReverbGetDecayTime(ReverbContext *pContext){ +uint32_t ReverbGetDecayTime(ReverbContext *pContext){ //LOGV("\tReverbGetDecayTime start"); LVREV_ControlParams_st ActiveParams; /* Current control Parameters */ @@ -1181,7 +1181,7 @@ int32_t ReverbGetDecayTime(ReverbContext *pContext){ } //LOGV("\tReverbGetDecayTime end"); - return ActiveParams.T60; + return (uint32_t)ActiveParams.T60; } //---------------------------------------------------------------------------- @@ -1606,7 +1606,7 @@ int Reverb_getParameter(ReverbContext *pContext, // *(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_getParameter(ReverbContext *pContext, 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 @@ int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){ return -EINVAL; } pContext->nextPreset = preset; + return 0; } switch (param){ @@ -1724,10 +1726,10 @@ int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){ //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 @@ int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){ //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 c79f913237ae..57f007264670 100644 --- a/native/android/input.cpp +++ b/native/android/input.cpp @@ -84,6 +84,10 @@ int32_t AMotionEvent_getAction(const AInputEvent* motion_event) { 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 5b62da44336e..9da122b6f842 100644 --- a/native/include/android/input.h +++ b/native/include/android/input.h @@ -247,6 +247,22 @@ enum { }; /* + * 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 @@ int64_t AKeyEvent_getEventTime(const AInputEvent* key_event); /* 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 3db5dc11baec..e454c0867b31 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -668,7 +668,7 @@ class BackupManagerService extends IBackupManager.Stub { 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 @@ class BackupManagerService extends IBackupManager.Stub { 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 @@ class BackupManagerService extends IBackupManager.Stub { 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 @@ class BackupManagerService extends IBackupManager.Stub { 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 @@ class BackupManagerService extends IBackupManager.Stub { } } + 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 @@ class BackupManagerService extends IBackupManager.Stub { } } } - 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 @@ class BackupManagerService extends IBackupManager.Stub { } } + // ----- 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 4a0df597ccaf..0b1a4a3ee314 100644 --- a/services/java/com/android/server/DeviceStorageMonitorService.java +++ b/services/java/com/android/server/DeviceStorageMonitorService.java @@ -69,10 +69,12 @@ class DeviceStorageMonitorService extends Binder { 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 @@ class DeviceStorageMonitorService extends Binder { 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 @@ class DeviceStorageMonitorService extends Binder { 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 @@ class DeviceStorageMonitorService extends Binder { 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 @@ class DeviceStorageMonitorService extends Binder { 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 @@ class DeviceStorageMonitorService extends Binder { 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 @@ class DeviceStorageMonitorService extends Binder { 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 @@ class DeviceStorageMonitorService extends Binder { 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 @@ class DeviceStorageMonitorService extends Binder { 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 8da0cf110f1f..dbc59ef9dfd5 100644 --- a/services/java/com/android/server/InputWindow.java +++ b/services/java/com/android/server/InputWindow.java @@ -34,9 +34,17 @@ public final class InputWindow { // 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 3841f75c7cc5..0bc9b615c032 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -5218,6 +5218,14 @@ public class WindowManagerService extends IWindowManager.Stub 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 89a162764b15..3142ee454870 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.Set; 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen boolean mBooting = false; boolean mWaitingUpdate = false; boolean mDidUpdate = false; + boolean mOnBattery = false; Context mContext; @@ -1381,8 +1383,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } + @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 6d1fbabc73ed..67df707341ed 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -131,6 +131,13 @@ class ProcessRecord { 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 @@ class ProcessRecord { 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 a237ee94bfb3..7af5e9581722 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -169,6 +169,12 @@ static struct { 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 @@ public: 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 @@ private: 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 @@ private: 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 @@ private: // 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 @@ private: 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::getKeyRepeatTimeout() { } } +nsecs_t NativeInputManager::getKeyRepeatDelay() { + return milliseconds_to_nanoseconds(50); +} + int32_t NativeInputManager::getMaxEventsPerSecond() { if (mMaxEventsPerSecond < 0) { JNIEnv* env = jniEnv(); @@ -1117,6 +1137,18 @@ bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj, gInputWindowClassInfo.frameLeft); jint frameTop = env->GetIntField(windowObj, gInputWindowClassInfo.frameTop); + jint frameRight = env->GetIntField(windowObj, + gInputWindowClassInfo.frameRight); + jint frameBottom = env->GetIntField(windowObj, + gInputWindowClassInfo.frameBottom); + jint visibleFrameLeft = env->GetIntField(windowObj, + gInputWindowClassInfo.visibleFrameLeft); + jint visibleFrameTop = env->GetIntField(windowObj, + gInputWindowClassInfo.visibleFrameTop); + jint visibleFrameRight = env->GetIntField(windowObj, + gInputWindowClassInfo.visibleFrameRight); + jint visibleFrameBottom = env->GetIntField(windowObj, + gInputWindowClassInfo.visibleFrameBottom); jint touchableAreaLeft = env->GetIntField(windowObj, gInputWindowClassInfo.touchableAreaLeft); jint touchableAreaTop = env->GetIntField(windowObj, @@ -1144,6 +1176,12 @@ bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj, 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 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin /* 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 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin 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 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin releaseTouchedWindowLd(); mTouchedWindow = newTouchedWindow; + mTouchedWindowIsObscured = obscured; if (newTouchedWindow->hasWallpaper) { mTouchedWallpaperWindows.appendVector(mWallpaperWindows); @@ -1557,21 +1601,31 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin 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 @@ int32_t NativeInputManager::waitForTouchedWindowLd(MotionEvent* motionEvent, uin void NativeInputManager::releaseTouchedWindowLd() { mTouchedWindow = NULL; + mTouchedWindowIsObscured = false; mTouchedWallpaperWindows.clear(); } @@ -1661,6 +1716,20 @@ bool NativeInputManager::checkInjectionPermission(const InputWindow* window, 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 @@ void NativeInputManager::dumpDispatchStateLd(String8& dump) { 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 @@ void NativeInputManager::dumpDispatchStateLd(String8& dump) { // ---------------------------------------------------------------------------- +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 @@ int register_android_server_InputManager(JNIEnv* env) { 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 c1232e803d98..caec7e1da592 100644 --- a/telephony/java/com/android/internal/telephony/CallManager.java +++ b/telephony/java/com/android/internal/telephony/CallManager.java @@ -466,6 +466,33 @@ public final class CallManager { } /** + * 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 8a5a6aee7487..5fef6de70a25 100644 --- a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java +++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java @@ -57,7 +57,7 @@ public abstract class IccSmsInterfaceManager extends ISms.Stub { * @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 @@ public abstract class IccSmsInterfaceManager extends ISms.Stub { * 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 @@ public abstract class IccSmsInterfaceManager extends ISms.Stub { * 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 @@ public abstract class IccSmsInterfaceManager extends ISms.Stub { * <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 606b52d60960..917e1d823a8a 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.Cursor; 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 @@ public abstract class SMSDispatcher extends Handler { // 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 @@ public abstract class SMSDispatcher extends Handler { * 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 @@ public abstract class SMSDispatcher extends Handler { * <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 @@ public abstract class SMSDispatcher extends Handler { * 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 @@ public abstract class SMSDispatcher extends Handler { * <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 @@ public abstract class SMSDispatcher extends Handler { 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 4508e9a4d741..f48c956356a1 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 @@ public class CDMAPhone extends PhoneBase { CdmaCallTracker mCT; CdmaSMSDispatcher mSMS; CdmaServiceStateTracker mSST; - RuimFileHandler mRuimFileHandler; RuimRecords mRuimRecords; RuimCard mRuimCard; ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>(); @@ -158,7 +157,7 @@ public class CDMAPhone extends PhoneBase { 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 cfcfd98b6840..e97549dc18f7 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.IccConstants; 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 class RuimSmsInterfaceManager extends IccSmsInterfaceManager { } }; - 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 e5ca51932641..689a97265ef7 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 @@ public class GSMPhone extends PhoneBase { 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 @@ public class GSMPhone extends PhoneBase { 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 2028ca4a78a8..67ecc77a320a 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 android.util.Log; 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 class SimSmsInterfaceManager extends IccSmsInterfaceManager { } }; - public SimSmsInterfaceManager(GSMPhone phone) { + public SimSmsInterfaceManager(GSMPhone phone, SMSDispatcher dispatcher) { super(phone); - mDispatcher = new GsmSMSDispatcher(phone); + mDispatcher = dispatcher; } public void dispose() { |