Merge "Pressed states for the notification panel's title area."
diff --git a/api/current.xml b/api/current.xml
index f98edab..c1d2f66 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -220707,6 +220707,17 @@
<parameter name="autoScale" type="boolean">
</parameter>
</method>
+<method name="buildLayer"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="cancelLongPress"
return="void"
abstract="false"
@@ -233470,6 +233481,17 @@
visibility="protected"
>
</method>
+<method name="getBackgroundColor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getDetachWallpaper"
return="boolean"
abstract="false"
@@ -233755,6 +233777,19 @@
<parameter name="listener" type="android.view.animation.Animation.AnimationListener">
</parameter>
</method>
+<method name="setBackgroundColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bg" type="int">
+</parameter>
+</method>
<method name="setDetachWallpaper"
return="void"
abstract="false"
@@ -266669,7 +266704,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
</parameter>
</method>
</interface>
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index 8b59554..22dd3c7 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -168,7 +168,9 @@
*/
private final HashMap<View, Animator> pendingAnimations = new HashMap<View, Animator>();
private final HashMap<View, Animator> currentChangingAnimations = new HashMap<View, Animator>();
- private final HashMap<View, Animator> currentVisibilityAnimations =
+ private final HashMap<View, Animator> currentAppearingAnimations =
+ new HashMap<View, Animator>();
+ private final HashMap<View, Animator> currentDisappearingAnimations =
new HashMap<View, Animator>();
/**
@@ -709,7 +711,8 @@
* @return true if any animations in the transition are running.
*/
public boolean isRunning() {
- return (currentChangingAnimations.size() > 0 || currentVisibilityAnimations.size() > 0);
+ return (currentChangingAnimations.size() > 0 || currentAppearingAnimations.size() > 0 ||
+ currentDisappearingAnimations.size() > 0);
}
/**
@@ -721,17 +724,74 @@
* @hide
*/
public void cancel() {
- HashMap<View, Animator> currentAnimCopy =
- (HashMap<View, Animator>) currentChangingAnimations.clone();
- for (Animator anim : currentAnimCopy.values()) {
- anim.cancel();
+ if (currentChangingAnimations.size() > 0) {
+ HashMap<View, Animator> currentAnimCopy =
+ (HashMap<View, Animator>) currentChangingAnimations.clone();
+ for (Animator anim : currentAnimCopy.values()) {
+ anim.cancel();
+ }
+ currentChangingAnimations.clear();
}
- currentChangingAnimations.clear();
- currentAnimCopy = (HashMap<View, Animator>) currentVisibilityAnimations.clone();
- for (Animator anim : currentAnimCopy.values()) {
- anim.end();
+ if (currentAppearingAnimations.size() > 0) {
+ HashMap<View, Animator> currentAnimCopy =
+ (HashMap<View, Animator>) currentAppearingAnimations.clone();
+ for (Animator anim : currentAnimCopy.values()) {
+ anim.end();
+ }
+ currentAppearingAnimations.clear();
}
- currentVisibilityAnimations.clear();
+ if (currentDisappearingAnimations.size() > 0) {
+ HashMap<View, Animator> currentAnimCopy =
+ (HashMap<View, Animator>) currentDisappearingAnimations.clone();
+ for (Animator anim : currentAnimCopy.values()) {
+ anim.end();
+ }
+ currentDisappearingAnimations.clear();
+ }
+ }
+
+ /**
+ * Cancels the specified type of transition. Note that we cancel() the changing animations
+ * but end() the visibility animations. This is because this method is currently called
+ * in the context of starting a new transition, so we want to move things from their mid-
+ * transition positions, but we want them to have their end-transition visibility.
+ *
+ * @hide
+ */
+ public void cancel(int transitionType) {
+ switch (transitionType) {
+ case CHANGE_APPEARING:
+ case CHANGE_DISAPPEARING:
+ if (currentChangingAnimations.size() > 0) {
+ HashMap<View, Animator> currentAnimCopy =
+ (HashMap<View, Animator>) currentChangingAnimations.clone();
+ for (Animator anim : currentAnimCopy.values()) {
+ anim.cancel();
+ }
+ currentChangingAnimations.clear();
+ }
+ break;
+ case APPEARING:
+ if (currentAppearingAnimations.size() > 0) {
+ HashMap<View, Animator> currentAnimCopy =
+ (HashMap<View, Animator>) currentAppearingAnimations.clone();
+ for (Animator anim : currentAnimCopy.values()) {
+ anim.end();
+ }
+ currentAppearingAnimations.clear();
+ }
+ break;
+ case DISAPPEARING:
+ if (currentDisappearingAnimations.size() > 0) {
+ HashMap<View, Animator> currentAnimCopy =
+ (HashMap<View, Animator>) currentDisappearingAnimations.clone();
+ for (Animator anim : currentAnimCopy.values()) {
+ anim.end();
+ }
+ currentDisappearingAnimations.clear();
+ }
+ break;
+ }
}
/**
@@ -741,7 +801,7 @@
* @param child The View being added to the ViewGroup.
*/
private void runAppearingTransition(final ViewGroup parent, final View child) {
- Animator currentAnimation = currentVisibilityAnimations.get(child);
+ Animator currentAnimation = currentDisappearingAnimations.get(child);
if (currentAnimation != null) {
currentAnimation.cancel();
}
@@ -764,14 +824,14 @@
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator anim) {
- currentVisibilityAnimations.remove(child);
+ currentAppearingAnimations.remove(child);
for (TransitionListener listener : mListeners) {
listener.endTransition(LayoutTransition.this, parent, child, APPEARING);
}
}
});
}
- currentVisibilityAnimations.put(child, anim);
+ currentAppearingAnimations.put(child, anim);
anim.start();
}
@@ -782,7 +842,7 @@
* @param child The View being removed from the ViewGroup.
*/
private void runDisappearingTransition(final ViewGroup parent, final View child) {
- Animator currentAnimation = currentVisibilityAnimations.get(child);
+ Animator currentAnimation = currentAppearingAnimations.get(child);
if (currentAnimation != null) {
currentAnimation.cancel();
}
@@ -802,7 +862,7 @@
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator anim) {
- currentVisibilityAnimations.remove(child);
+ currentDisappearingAnimations.remove(child);
for (TransitionListener listener : mListeners) {
listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING);
}
@@ -812,7 +872,7 @@
if (anim instanceof ObjectAnimator) {
((ObjectAnimator) anim).setCurrentPlayTime(0);
}
- currentVisibilityAnimations.put(child, anim);
+ currentDisappearingAnimations.put(child, anim);
anim.start();
}
@@ -826,9 +886,10 @@
* @param child The View being added to the ViewGroup.
*/
public void addChild(ViewGroup parent, View child) {
- if (isRunning()) {
- cancel();
- }
+ // Want disappearing animations to finish up before proceeding
+ cancel(DISAPPEARING);
+ // Also, cancel changing animations so that we start fresh ones from current locations
+ cancel(CHANGE_APPEARING);
if (mListeners != null) {
for (TransitionListener listener : mListeners) {
listener.startTransition(this, parent, child, APPEARING);
@@ -861,9 +922,10 @@
* @param child The View being removed from the ViewGroup.
*/
public void removeChild(ViewGroup parent, View child) {
- if (isRunning()) {
- cancel();
- }
+ // Want appearing animations to finish up before proceeding
+ cancel(APPEARING);
+ // Also, cancel changing animations so that we start fresh ones from current locations
+ cancel(CHANGE_DISAPPEARING);
if (mListeners != null) {
for (TransitionListener listener : mListeners) {
listener.startTransition(this, parent, child, DISAPPEARING);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8f9a76b..b409f2f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -98,7 +98,6 @@
import java.util.regex.Pattern;
import dalvik.system.CloseGuard;
-import dalvik.system.SamplingProfiler;
final class SuperNotCalledException extends AndroidRuntimeException {
public SuperNotCalledException(String msg) {
@@ -355,6 +354,7 @@
boolean restrictedBackupMode;
Configuration config;
boolean handlingProfiling;
+ Bundle coreSettings;
public String toString() {
return "AppBindData{appInfo=" + appInfo + "}";
}
@@ -552,7 +552,7 @@
ComponentName instrumentationName, String profileFile,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
int debugMode, boolean isRestrictedBackupMode, Configuration config,
- Map<String, IBinder> services) {
+ Map<String, IBinder> services, Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
@@ -570,6 +570,7 @@
data.debugMode = debugMode;
data.restrictedBackupMode = isRestrictedBackupMode;
data.config = config;
+ data.coreSettings = coreSettings;
queueOrSendMessage(H.BIND_APPLICATION, data);
}
@@ -896,6 +897,10 @@
private void printRow(PrintWriter pw, String format, Object...objs) {
pw.println(String.format(format, objs));
}
+
+ public void setCoreSettings(Bundle settings) {
+ queueOrSendMessage(H.SET_CORE_SETTINGS, settings);
+ }
}
private final class H extends Handler {
@@ -937,6 +942,7 @@
public static final int DUMP_HEAP = 135;
public static final int DUMP_ACTIVITY = 136;
public static final int SLEEPING = 137;
+ public static final int SET_CORE_SETTINGS = 138;
String codeToString(int code) {
if (DEBUG_MESSAGES) {
switch (code) {
@@ -978,6 +984,7 @@
case DUMP_HEAP: return "DUMP_HEAP";
case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
case SLEEPING: return "SLEEPING";
+ case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
}
}
return "(unknown)";
@@ -1113,6 +1120,9 @@
case SLEEPING:
handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
break;
+ case SET_CORE_SETTINGS:
+ handleSetCoreSettings((Bundle) msg.obj);
+ break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
}
@@ -2709,6 +2719,14 @@
}
}
+ private void handleSetCoreSettings(Bundle coreSettings) {
+ if (mBoundApplication != null) {
+ synchronized (mBoundApplication) {
+ mBoundApplication.coreSettings = coreSettings;
+ }
+ }
+ }
+
private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
final int N = results.size();
for (int i=0; i<N; i++) {
@@ -3971,6 +3989,20 @@
}
}
+ public int getIntCoreSetting(String key, int defaultValue) {
+ if (mBoundApplication == null) {
+ return defaultValue;
+ }
+ synchronized (mBoundApplication) {
+ Bundle coreSettings = mBoundApplication.coreSettings;
+ if (coreSettings != null) {
+ return coreSettings.getInt(key, defaultValue);
+ } else {
+ return defaultValue;
+ }
+ }
+ }
+
public static final void main(String[] args) {
SamplingProfilerIntegration.start();
diff --git a/core/java/android/app/AppGlobals.java b/core/java/android/app/AppGlobals.java
index 9a39129..55515b8 100644
--- a/core/java/android/app/AppGlobals.java
+++ b/core/java/android/app/AppGlobals.java
@@ -38,12 +38,23 @@
public static String getInitialPackage() {
return ActivityThread.currentPackageName();
}
-
+
/**
* Return the raw interface to the package manager.
- * @return
+ * @return The package manager.
*/
public static IPackageManager getPackageManager() {
return ActivityThread.getPackageManager();
}
+
+ /**
+ * Gets the value of an integer core setting.
+ *
+ * @param key The setting key.
+ * @param defaultValue The setting default value.
+ * @return The core settings.
+ */
+ public static int getIntCoreSetting(String key, int defaultValue) {
+ return ActivityThread.currentActivityThread().getIntCoreSetting(key, defaultValue);
+ }
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index ef92933..aa26b04 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -257,10 +257,11 @@
boolean restrictedBackupMode = (data.readInt() != 0);
Configuration config = Configuration.CREATOR.createFromParcel(data);
HashMap<String, IBinder> services = data.readHashMap(null);
+ Bundle coreSettings = data.readBundle();
bindApplication(packageName, info,
providers, testName, profileName,
testArgs, testWatcher, testMode, restrictedBackupMode,
- config, services);
+ config, services, coreSettings);
return true;
}
@@ -454,6 +455,13 @@
}
return true;
}
+
+ case SET_CORE_SETTINGS: {
+ data.enforceInterface(IApplicationThread.descriptor);
+ Bundle settings = data.readBundle();
+ setCoreSettings(settings);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -712,7 +720,7 @@
List<ProviderInfo> providers, ComponentName testName,
String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode,
boolean restrictedBackupMode, Configuration config,
- Map<String, IBinder> services) throws RemoteException {
+ Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeString(packageName);
@@ -731,6 +739,7 @@
data.writeInt(restrictedBackupMode ? 1 : 0);
config.writeToParcel(data, 0);
data.writeMap(services);
+ data.writeBundle(coreSettings);
mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
@@ -938,4 +947,11 @@
mRemote.transact(DUMP_ACTIVITY_TRANSACTION, data, null, 0);
data.recycle();
}
+
+ public void setCoreSettings(Bundle coreSettings) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeBundle(coreSettings);
+ mRemote.transact(SET_CORE_SETTINGS, data, null, IBinder.FLAG_ONEWAY);
+ }
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 16c3c5c..55177a9 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -82,7 +82,8 @@
void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
ComponentName testName, String profileName, Bundle testArguments,
IInstrumentationWatcher testWatcher, int debugMode, boolean restrictedBackupMode,
- Configuration config, Map<String, IBinder> services) throws RemoteException;
+ Configuration config, Map<String, IBinder> services,
+ Bundle coreSettings) throws RemoteException;
void scheduleExit() throws RemoteException;
void scheduleSuicide() throws RemoteException;
void requestThumbnail(IBinder token) throws RemoteException;
@@ -110,6 +111,7 @@
void scheduleCrash(String msg) throws RemoteException;
void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
throws RemoteException;
+ void setCoreSettings(Bundle coreSettings) throws RemoteException;
String descriptor = "android.app.IApplicationThread";
@@ -151,4 +153,5 @@
int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
int CLEAR_DNS_CACHE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
int SET_HTTP_PROXY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
+ int SET_CORE_SETTINGS = IBinder.FIRST_CALL_TRANSACTION+39;
}
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index b96defe..4e22ba0 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -187,6 +187,7 @@
public void onDestroyView() {
mList = null;
mHandler.removeCallbacks(mRequestFocus);
+ mHandler.removeMessages(MSG_BIND_PREFERENCES);
super.onDestroyView();
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1718189..6deb5a0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2698,6 +2698,12 @@
"accessibility_web_content_key_bindings";
/**
+ * The timout for considering a press to be a long press in milliseconds.
+ * @hide
+ */
+ public static final String LONG_PRESS_TIMEOUT = "long_press_timeout";
+
+ /**
* Setting to always use the default text-to-speech settings regardless
* of the application settings.
* 1 = override application settings,
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index fc01ef2..53fa7c2 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -1169,6 +1169,30 @@
return ret;
}
+ /**
+ * Returns the next cursor position in the run. This avoids placing the cursor between
+ * surrogates, between characters that form conjuncts, between base characters and combining
+ * marks, or within a reordering cluster.
+ *
+ * <p>The context is the shaping context for cursor movement, generally the bounds of the metric
+ * span enclosing the cursor in the direction of movement.
+ * <code>contextStart</code>, <code>contextEnd</code> and <code>offset</code> are relative to
+ * the start of the string.</p>
+ *
+ * <p>If cursorOpt is CURSOR_AT and the offset is not a valid cursor position,
+ * this returns -1. Otherwise this will never return a value before contextStart or after
+ * contextEnd.</p>
+ *
+ * @param contextStart the start index of the context
+ * @param contextEnd the (non-inclusive) end index of the context
+ * @param flags either DIRECTION_RTL or DIRECTION_LTR
+ * @param offset the cursor position to move from
+ * @param cursorOpt how to move the cursor, one of CURSOR_AFTER,
+ * CURSOR_AT_OR_AFTER, CURSOR_BEFORE,
+ * CURSOR_AT_OR_BEFORE, or CURSOR_AT
+ * @param p the Paint object that is requesting this information
+ * @return the offset of the next position, or -1
+ */
public int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset,
int cursorOpt, Paint p) {
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index a26dd04..076f712 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -937,6 +937,7 @@
private static native int nativeSetSource(int nativePtr, int source);
private static native int nativeGetAction(int nativePtr);
private static native void nativeSetAction(int nativePtr, int action);
+ private static native boolean nativeIsTouchEvent(int nativePtr);
private static native int nativeGetFlags(int nativePtr);
private static native int nativeGetEdgeFlags(int nativePtr);
private static native void nativeSetEdgeFlags(int nativePtr, int action);
@@ -1275,19 +1276,7 @@
* @hide
*/
public final boolean isTouchEvent() {
- if ((getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
- switch (getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_MOVE:
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_POINTER_UP:
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_OUTSIDE:
- return true;
- }
- }
- return false;
+ return nativeIsTouchEvent(mNativePtr);
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2170d72..32c9e27 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8488,6 +8488,7 @@
* {@link #LAYER_TYPE_HARDWARE}
*
* @see #setLayerType(int, android.graphics.Paint)
+ * @see #buildLayer()
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
* @see #LAYER_TYPE_HARDWARE
@@ -8497,6 +8498,36 @@
}
/**
+ * Forces this view's layer to be created and this view to be rendered
+ * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
+ * invoking this method will have no effect.
+ *
+ * This method can for instance be used to render a view into its layer before
+ * starting an animation. If this view is complex, rendering into the layer
+ * before starting the animation will avoid skipping frames.
+ *
+ * @throws IllegalStateException If this view is not attached to a window
+ *
+ * @see #setLayerType(int, android.graphics.Paint)
+ */
+ public void buildLayer() {
+ if (mLayerType == LAYER_TYPE_NONE) return;
+
+ if (mAttachInfo == null) {
+ throw new IllegalStateException("This view must be attached to a window first");
+ }
+
+ switch (mLayerType) {
+ case LAYER_TYPE_HARDWARE:
+ getHardwareLayer();
+ break;
+ case LAYER_TYPE_SOFTWARE:
+ buildDrawingCache(true);
+ break;
+ }
+ }
+
+ /**
* <p>Returns a hardware layer that can be used to draw this view again
* without executing its draw method.</p>
*
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index cc4e89c..d95c5b0 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -16,8 +16,11 @@
package android.view;
+import android.app.AppGlobals;
import android.content.Context;
import android.content.res.Configuration;
+import android.os.Bundle;
+import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.SparseArray;
@@ -74,7 +77,7 @@
* Defines the duration in milliseconds before a press turns into
* a long press
*/
- private static final int LONG_PRESS_TIMEOUT = 500;
+ private static final int DEFAULTLONG_PRESS_TIMEOUT = 500;
/**
* Defines the duration in milliseconds a user needs to hold down the
@@ -320,15 +323,16 @@
public static int getPressedStateDuration() {
return PRESSED_STATE_DURATION;
}
-
+
/**
* @return the duration in milliseconds before a press turns into
* a long press
*/
public static int getLongPressTimeout() {
- return LONG_PRESS_TIMEOUT;
+ return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT,
+ DEFAULTLONG_PRESS_TIMEOUT);
}
-
+
/**
* @return the duration in milliseconds we will wait to see if a touch event
* is a tap or a scroll. If the user does not move within this interval, it is
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index af4c221..3153ac5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3001,8 +3001,10 @@
private void addViewInner(View child, int index, LayoutParams params,
boolean preventRequestLayout) {
- if (mTransition != null && mTransition.isRunning()) {
- mTransition.cancel();
+ if (mTransition != null) {
+ // Don't prevent other add transitions from completing, but cancel remove
+ // transitions to let them complete the process before we add to the container
+ mTransition.cancel(LayoutTransition.DISAPPEARING);
}
if (child.getParent() != null) {
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index be68cb9..334c68e 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -573,7 +573,21 @@
* {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
*/
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
-
+
+ /**
+ * Called from the input reader thread before a motion is enqueued when the screen is off.
+ *
+ * <p>There are some actions that need to be handled here because they
+ * affect the power state of the device, for example, waking on motions.
+ * Generally, it's best to keep as little as possible in the queue thread
+ * because it's the most fragile.
+ * @param policyFlags The policy flags associated with the motion.
+ *
+ * @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
+ * {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
+ */
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags);
+
/**
* Called from the input dispatcher thread before a key is dispatched to a window.
*
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 13d0ec1..87c759c 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -181,6 +181,11 @@
private int mZAdjustment;
/**
+ * Desired background color behind animation.
+ */
+ private int mBackgroundColor;
+
+ /**
* scalefactor to apply to pivot points, etc. during animation. Subclasses retrieve the
* value via getScaleFactor().
*/
@@ -236,6 +241,8 @@
setZAdjustment(a.getInt(com.android.internal.R.styleable.Animation_zAdjustment, ZORDER_NORMAL));
+ setBackgroundColor(a.getInt(com.android.internal.R.styleable.Animation_background, 0));
+
setDetachWallpaper(a.getBoolean(com.android.internal.R.styleable.Animation_detachWallpaper, false));
ensureInterpolator();
@@ -568,6 +575,16 @@
}
/**
+ * Set background behind animation.
+ *
+ * @param bg The background color. If 0, no background. Currently must
+ * be black, with any desired alpha level.
+ */
+ public void setBackgroundColor(int bg) {
+ mBackgroundColor = bg;
+ }
+
+ /**
* The scale factor is set by the call to <code>getTransformation</code>. Overrides of
* {@link #getTransformation(long, Transformation, float)} will get this value
* directly. Overrides of {@link #applyTransformation(float, Transformation)} can
@@ -690,6 +707,13 @@
}
/**
+ * Returns the background color behind the animation.
+ */
+ public int getBackgroundColor() {
+ return mBackgroundColor;
+ }
+
+ /**
* Return value of {@link #setDetachWallpaper(boolean)}.
* @attr ref android.R.styleable#Animation_detachWallpaper
*/
diff --git a/core/java/android/widget/EdgeGlow.java b/core/java/android/widget/EdgeGlow.java
index c2cb0a0..75cef38 100644
--- a/core/java/android/widget/EdgeGlow.java
+++ b/core/java/android/widget/EdgeGlow.java
@@ -260,7 +260,7 @@
glowHeight * MAX_GLOW_HEIGHT);
if (mWidth < mMinWidth) {
// Center the glow and clip it.
- int glowLeft = (mWidth - glowWidth)/2;
+ int glowLeft = (mWidth - mMinWidth)/2;
mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom);
} else {
// Stretch the glow to fit.
@@ -274,7 +274,7 @@
int edgeBottom = (int) (edgeHeight * mEdgeScaleY);
if (mWidth < mMinWidth) {
// Center the edge and clip it.
- int edgeLeft = (mWidth - edgeWidth)/2;
+ int edgeLeft = (mWidth - mMinWidth)/2;
mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom);
} else {
// Stretch the edge to fit.
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index b014006..97cba23 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -429,6 +429,12 @@
event->setAction(action);
}
+static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
+ jint nativePtr) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ return event->isTouchEvent();
+}
+
static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz,
jint nativePtr) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
@@ -661,6 +667,9 @@
{ "nativeSetAction",
"(II)V",
(void*)android_view_MotionEvent_nativeSetAction },
+ { "nativeIsTouchEvent",
+ "(I)Z",
+ (void*)android_view_MotionEvent_nativeIsTouchEvent },
{ "nativeGetFlags",
"(I)I",
(void*)android_view_MotionEvent_nativeGetFlags },
diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
index b479543..66d982f 100644
--- a/core/res/res/anim/task_close_enter.xml
+++ b/core/res/res/anim/task_close_enter.xml
@@ -18,7 +18,7 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:detachWallpaper="true" android:shareInterpolator="false">
+ android:background="#ff000000" android:shareInterpolator="false">
<scale android:fromXScale="1.0" android:toXScale="1.0"
android:fromYScale="0.95" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
index e561e97..312946b 100644
--- a/core/res/res/anim/task_close_exit.xml
+++ b/core/res/res/anim/task_close_exit.xml
@@ -18,7 +18,7 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:detachWallpaper="true" android:shareInterpolator="false">
+ android:background="#ff000000" android:shareInterpolator="false">
<scale android:fromXScale="1.0" android:toXScale="1.0"
android:fromYScale="1.0" android:toYScale="0.0"
android:pivotX="50%p" android:pivotY="50%p"
diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
index b3b3fd1..3dda797 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -18,7 +18,7 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:detachWallpaper="true" android:shareInterpolator="false">
+ android:background="#ff000000" android:shareInterpolator="false">
<scale android:fromXScale="1.0" android:toXScale="1.0"
android:fromYScale=".9" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
index 763b581..e377c2a 100644
--- a/core/res/res/anim/task_open_exit.xml
+++ b/core/res/res/anim/task_open_exit.xml
@@ -18,7 +18,7 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:detachWallpaper="true" android:shareInterpolator="false">
+ android:background="#ff000000" android:shareInterpolator="false">
<scale android:fromXScale="1.0" android:toXScale="1.0"
android:fromYScale="1.0" android:toYScale="0.0"
android:pivotX="50%p" android:pivotY="50%p"
diff --git a/core/res/res/drawable-hdpi/ic_paste_bubble_holo.png b/core/res/res/drawable-hdpi/ic_paste_bubble_holo.png
new file mode 100644
index 0000000..15bd8b2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_paste_bubble_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
index 2dabb5f..21e2fb9 100644
--- a/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
index 8069452..8e9c02c 100644
--- a/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_paste_window.9.png b/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
index 7cd000b..6654e4d 100644
--- a/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
+++ b/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
index 7cd000b..c564495 100644
--- a/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
+++ b/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left.png b/core/res/res/drawable-hdpi/text_select_handle_left.png
old mode 100755
new mode 100644
index 3743d91..e42a62e
--- a/core/res/res/drawable-hdpi/text_select_handle_left.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_left.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle.png b/core/res/res/drawable-hdpi/text_select_handle_middle.png
old mode 100755
new mode 100644
index 5a83c6c..00d47f2
--- a/core/res/res/drawable-hdpi/text_select_handle_middle.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right.png b/core/res/res/drawable-hdpi/text_select_handle_right.png
old mode 100755
new mode 100644
index 12a3dff..7426543
--- a/core/res/res/drawable-hdpi/text_select_handle_right.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_right.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_paste_bubble_holo.png b/core/res/res/drawable-mdpi/ic_paste_bubble_holo.png
new file mode 100644
index 0000000..e483e84
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_paste_bubble_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
index f873edb..b888135 100644
--- a/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
index ba11cfb..1cc1f7f 100644
--- a/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_paste_window.9.png b/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
index 6b98c13..41886eb 100644
--- a/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
+++ b/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
index d87c35b..d8ae54c 100644
--- a/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
+++ b/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left.png b/core/res/res/drawable-mdpi/text_select_handle_left.png
index 4ee2f42..959887f 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_left.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_left.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle.png b/core/res/res/drawable-mdpi/text_select_handle_middle.png
index 3d16052..42d4e1a 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_middle.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right.png b/core/res/res/drawable-mdpi/text_select_handle_right.png
index 3d38928..61f9c12 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_right.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_right.png
Binary files differ
diff --git a/core/res/res/layout/text_edit_paste_window.xml b/core/res/res/layout/text_edit_paste_window.xml
index 575b98e..01e5530 100644
--- a/core/res/res/layout/text_edit_paste_window.xml
+++ b/core/res/res/layout/text_edit_paste_window.xml
@@ -24,8 +24,8 @@
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:paddingTop="8dip"
- android:paddingBottom="8dip"
- android:drawableLeft="@android:drawable/ic_menu_paste_light"
+ android:paddingBottom="12dip"
+ android:drawableLeft="@android:drawable/ic_paste_bubble_holo"
android:drawablePadding="8dip"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
diff --git a/core/res/res/layout/text_edit_side_paste_window.xml b/core/res/res/layout/text_edit_side_paste_window.xml
index 689a039..6651786 100644
--- a/core/res/res/layout/text_edit_side_paste_window.xml
+++ b/core/res/res/layout/text_edit_side_paste_window.xml
@@ -25,7 +25,7 @@
android:paddingRight="16dip"
android:paddingTop="8dip"
android:paddingBottom="8dip"
- android:drawableLeft="@android:drawable/ic_menu_paste_light"
+ android:drawableLeft="@android:drawable/ic_paste_bubble_holo"
android:drawablePadding="8dip"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3b225a4..d3b1062 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3596,6 +3596,10 @@
content for the duration of the animation. -->
<enum name="bottom" value="-1" />
</attr>
+ <!-- Special background behind animation. Only for use with window
+ animations. Can only be a color, and only black. If 0, the
+ default, there is no background. -->
+ <attr name="background" />
<!-- Special option for window animations: if this window is on top
of a wallpaper, don't animate the wallpaper with it. -->
<attr name="detachWallpaper" format="boolean" />
diff --git a/data/sounds/effects/ogg/Lock.ogg b/data/sounds/effects/ogg/Lock.ogg
index 2e57d9e..a25513f 100644
--- a/data/sounds/effects/ogg/Lock.ogg
+++ b/data/sounds/effects/ogg/Lock.ogg
Binary files differ
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 6caf678..c541456 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -479,6 +479,9 @@
*/
public int acquireRights(DrmInfoRequest drmInfoRequest) {
DrmInfo drmInfo = acquireDrmInfo(drmInfoRequest);
+ if (null == drmInfo) {
+ return ERROR_UNKNOWN;
+ }
return processDrmInfo(drmInfo);
}
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index cce9129..7956788 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -55,17 +55,25 @@
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp<IOMX> getOMX() = 0;
- // codecs usage tracking for the battery app
+ // codecs and audio devices usage tracking for the battery app
enum BatteryDataBits {
// tracking audio codec
- kBatteryDataTrackAudio = 1,
+ kBatteryDataTrackAudio = 0x1,
// tracking video codec
- kBatteryDataTrackVideo = 2,
+ kBatteryDataTrackVideo = 0x2,
// codec is started, otherwise codec is paused
- kBatteryDataCodecStarted = 4,
+ kBatteryDataCodecStarted = 0x4,
// tracking decoder (for media player),
// otherwise tracking encoder (for media recorder)
- kBatteryDataTrackDecoder = 8,
+ kBatteryDataTrackDecoder = 0x8,
+ // start to play an audio on an audio device
+ kBatteryDataAudioFlingerStart = 0x10,
+ // stop/pause the audio playback
+ kBatteryDataAudioFlingerStop = 0x20,
+ // audio is rounted to speaker
+ kBatteryDataSpeakerOn = 0x40,
+ // audio is rounted to devices other than speaker
+ kBatteryDataOtherAudioDeviceOn = 0x80,
};
virtual void addBatteryData(uint32_t params) = 0;
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 082f11c..e92d7f5 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -476,6 +476,11 @@
status_t writeToParcel(Parcel* parcel) const;
#endif
+ static bool isTouchEvent(int32_t source, int32_t action);
+ inline bool isTouchEvent() const {
+ return isTouchEvent(mSource, mAction);
+ }
+
// Low-level accessors.
inline const int32_t* getPointerIds() const { return mPointerIds.array(); }
inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); }
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index a80320e..0ed0866 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -616,6 +616,23 @@
}
#endif
+bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
+ if (source & AINPUT_SOURCE_CLASS_POINTER) {
+ // Specifically excludes HOVER_MOVE and SCROLL.
+ switch (action & AMOTION_EVENT_ACTION_MASK) {
+ case AMOTION_EVENT_ACTION_DOWN:
+ case AMOTION_EVENT_ACTION_MOVE:
+ case AMOTION_EVENT_ACTION_UP:
+ case AMOTION_EVENT_ACTION_POINTER_DOWN:
+ case AMOTION_EVENT_ACTION_POINTER_UP:
+ case AMOTION_EVENT_ACTION_CANCEL:
+ case AMOTION_EVENT_ACTION_OUTSIDE:
+ return true;
+ }
+ }
+ return false;
+}
+
// --- InputDeviceInfo ---
diff --git a/media/java/android/mtp/MtpClient.java b/media/java/android/mtp/MtpClient.java
index 6c8b228..c4ee19e 100644
--- a/media/java/android/mtp/MtpClient.java
+++ b/media/java/android/mtp/MtpClient.java
@@ -163,15 +163,6 @@
mContext.unregisterReceiver(mUsbReceiver);
}
- @Override
- protected void finalize() throws Throwable {
- try {
- close();
- } finally {
- super.finalize();
- }
- }
-
/**
* Registers a {@link android.mtp.MtpClient.Listener} interface to receive
* notifications when MTP or PTP devices are added or removed.
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index ec6188f..a42cca5 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -214,6 +214,15 @@
{
LOGV("MediaPlayerService created");
mNextConnId = 1;
+
+ mBatteryAudio.refCount = 0;
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ mBatteryAudio.deviceOn[i] = 0;
+ mBatteryAudio.lastTime[i] = 0;
+ mBatteryAudio.totalTime[i] = 0;
+ }
+ // speaker is on by default
+ mBatteryAudio.deviceOn[SPEAKER] = 1;
}
MediaPlayerService::~MediaPlayerService()
@@ -1777,12 +1786,88 @@
void MediaPlayerService::addBatteryData(uint32_t params)
{
Mutex::Autolock lock(mLock);
+
+ int32_t time = systemTime() / 1000000L;
+
+ // change audio output devices. This notification comes from AudioFlinger
+ if ((params & kBatteryDataSpeakerOn)
+ || (params & kBatteryDataOtherAudioDeviceOn)) {
+
+ int deviceOn[NUM_AUDIO_DEVICES];
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ deviceOn[i] = 0;
+ }
+
+ if ((params & kBatteryDataSpeakerOn)
+ && (params & kBatteryDataOtherAudioDeviceOn)) {
+ deviceOn[SPEAKER_AND_OTHER] = 1;
+ } else if (params & kBatteryDataSpeakerOn) {
+ deviceOn[SPEAKER] = 1;
+ } else {
+ deviceOn[OTHER_AUDIO_DEVICE] = 1;
+ }
+
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
+
+ if (mBatteryAudio.refCount > 0) { // if playing audio
+ if (!deviceOn[i]) {
+ mBatteryAudio.lastTime[i] += time;
+ mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
+ mBatteryAudio.lastTime[i] = 0;
+ } else {
+ mBatteryAudio.lastTime[i] = 0 - time;
+ }
+ }
+
+ mBatteryAudio.deviceOn[i] = deviceOn[i];
+ }
+ }
+ return;
+ }
+
+ // an sudio stream is started
+ if (params & kBatteryDataAudioFlingerStart) {
+ // record the start time only if currently no other audio
+ // is being played
+ if (mBatteryAudio.refCount == 0) {
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ if (mBatteryAudio.deviceOn[i]) {
+ mBatteryAudio.lastTime[i] -= time;
+ }
+ }
+ }
+
+ mBatteryAudio.refCount ++;
+ return;
+
+ } else if (params & kBatteryDataAudioFlingerStop) {
+ if (mBatteryAudio.refCount <= 0) {
+ LOGW("Battery track warning: refCount is <= 0");
+ return;
+ }
+
+ // record the stop time only if currently this is the only
+ // audio being played
+ if (mBatteryAudio.refCount == 1) {
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ if (mBatteryAudio.deviceOn[i]) {
+ mBatteryAudio.lastTime[i] += time;
+ mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
+ mBatteryAudio.lastTime[i] = 0;
+ }
+ }
+ }
+
+ mBatteryAudio.refCount --;
+ return;
+ }
+
int uid = IPCThreadState::self()->getCallingUid();
if (uid == AID_MEDIA) {
return;
}
int index = mBatteryData.indexOfKey(uid);
- int32_t time = systemTime() / 1000000L;
if (index < 0) { // create a new entry for this UID
BatteryUsageInfo info;
@@ -1792,7 +1877,10 @@
info.videoLastTime = 0;
info.refCount = 0;
- mBatteryData.add(uid, info);
+ if (mBatteryData.add(uid, info) == NO_MEMORY) {
+ LOGE("Battery track error: no memory for new app");
+ return;
+ }
}
BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
@@ -1837,6 +1925,26 @@
status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
Mutex::Autolock lock(mLock);
+
+ // audio output devices usage
+ int32_t time = systemTime() / 1000000L; //in ms
+ int32_t totalTime;
+
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ totalTime = mBatteryAudio.totalTime[i];
+
+ if (mBatteryAudio.deviceOn[i]
+ && (mBatteryAudio.lastTime[i] != 0)) {
+ int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
+ totalTime += tmpTime;
+ }
+
+ reply->writeInt32(totalTime);
+ // reset the total time
+ mBatteryAudio.totalTime[i] = 0;
+ }
+
+ // codec usage
BatteryUsageInfo info;
int size = mBatteryData.size();
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 1175ed0..ff6ccf54 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -225,6 +225,25 @@
};
KeyedVector<int, BatteryUsageInfo> mBatteryData;
+ enum {
+ SPEAKER,
+ OTHER_AUDIO_DEVICE,
+ SPEAKER_AND_OTHER,
+ NUM_AUDIO_DEVICES
+ };
+
+ struct BatteryAudioFlingerUsageInfo {
+ int refCount; // how many audio streams are being played
+ int deviceOn[NUM_AUDIO_DEVICES]; // whether the device is currently used
+ int32_t lastTime[NUM_AUDIO_DEVICES]; // in ms
+ // totalTime[]: total time of audio output devices usage
+ int32_t totalTime[NUM_AUDIO_DEVICES]; // in ms
+ };
+
+ // This varialble is used to record the usage of audio output device
+ // for battery app
+ BatteryAudioFlingerUsageInfo mBatteryAudio;
+
// Collect info of the codec usage from media player and media recorder
virtual void addBatteryData(uint32_t params);
// API for the Battery app to pull the data of codecs usage
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 2df6d68..bf06f947 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -121,4 +121,8 @@
<integer name="def_download_manager_max_bytes_over_mobile">-1</integer>
<!-- Default for Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE. <=0 if no limit -->
<integer name="def_download_manager_recommended_max_bytes_over_mobile">-1</integer>
+
+ <!-- Default for Settings.Secure.LONG_PRESS_TIMEOUT_MILLIS -->
+ <integer name="def_long_press_timeout_millis">500</integer>
+
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index f336f06..d901c2c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -819,6 +819,24 @@
upgradeVersion = 64;
}
+ if (upgradeVersion == 64) {
+ // New setting to configure the long press timeout.
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT INTO secure(name,value)"
+ + " VALUES(?,?);");
+ loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
+ R.integer.def_long_press_timeout_millis);
+ stmt.close();
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 65;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -1332,6 +1350,9 @@
loadSetting(stmt, Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
Integer.toString(recommendedMaxBytes));
}
+
+ loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
+ R.integer.def_long_press_timeout_millis);
} finally {
if (stmt != null) stmt.close();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index 1135b73..737a52b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -362,6 +362,9 @@
mRecentsContainer.addFooterView(footer, null, false);
mRecentsContainer.setAdapter(mListAdapter = new ActvityDescriptionAdapter(mContext));
mRecentsContainer.setOnItemClickListener(this);
+ final int leftPadding = mContext.getResources()
+ .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
+ mRecentsContainer.setOverScrollEffectPadding(leftPadding, 0);
mRecentsGlowView = findViewById(R.id.recents_glow);
mRecentsScrim = (View) findViewById(R.id.recents_bg_protect);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 36afd75..74dde9c 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -108,7 +108,8 @@
* action should be posted to a handler.
*
* @param keyCode The wake key, which may be relevant for configuring the
- * keyguard.
+ * keyguard. May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking for a reason
+ * other than a key press.
*/
abstract public void wakeWhenReadyTq(int keyCode);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index edab690..8d70a7b 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -201,7 +201,8 @@
* Be sure not to take any action that takes a long time; any significant
* action should be posted to a handler.
*
- * @param keyCode The wake key.
+ * @param keyCode The wake key. May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
+ * for a reason other than a key press.
*/
public boolean wakeWhenReadyTq(int keyCode) {
if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index b32a729..e7a9eb1 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -810,6 +810,28 @@
}
/**
+ * When a wake motion such as an external mouse movement is received when the screen
+ * is off and the keyguard is showing, we need to decide whether to actually turn
+ * on the screen, and if so, tell the keyguard to prepare itself and poke the wake
+ * lock when it is ready.
+ *
+ * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
+ * Be sure not to take any action that takes a long time; any significant
+ * action should be posted to a handler.
+ *
+ * @return Whether we poked the wake lock (and turned the screen on)
+ */
+ public boolean onWakeMotionWhenKeyguardShowingTq() {
+ if (DEBUG) Log.d(TAG, "onWakeMotionWhenKeyguardShowing()");
+
+ // give the keyguard view manager a chance to adjust the state of the
+ // keyguard based on the key that woke the device before poking
+ // the wake lock
+ wakeWhenReadyLocked(KeyEvent.KEYCODE_UNKNOWN);
+ return true;
+ }
+
+ /**
* Callbacks from {@link KeyguardViewManager}.
*/
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 75ef762..8e18f2a 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2364,6 +2364,25 @@
return result;
}
+ /** {@inheritDoc} */
+ @Override
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+ int result = 0;
+
+ final boolean isWakeMotion = (policyFlags
+ & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
+ if (isWakeMotion) {
+ if (mKeyguardMediator.isShowing()) {
+ // If the keyguard is showing, let it decide what to do with the wake motion.
+ mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
+ } else {
+ // Otherwise, wake the device ourselves.
+ result |= ACTION_POKE_USER_ACTIVITY;
+ }
+ }
+ return result;
+ }
+
class PassHeadsetKey implements Runnable {
KeyEvent mKeyEvent;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a07ebfc..2b08ab5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -24,6 +24,7 @@
#include <sys/time.h>
#include <sys/resource.h>
+#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
@@ -35,6 +36,7 @@
#include <media/AudioTrack.h>
#include <media/AudioRecord.h>
+#include <media/IMediaPlayerService.h>
#include <private/media/AudioTrackShared.h>
#include <private/media/AudioEffectShared.h>
@@ -121,6 +123,19 @@
#endif
}
+// To collect the amplifier usage
+static void addBatteryData(uint32_t params) {
+ sp<IBinder> binder =
+ defaultServiceManager()->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+ if (service.get() == NULL) {
+ LOGW("Cannot connect to the MediaPlayerService for battery tracking");
+ return;
+ }
+
+ service->addBatteryData(params);
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::AudioFlinger()
@@ -1833,6 +1848,27 @@
}
}
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+ // when changing the audio output device, call addBatteryData to notify
+ // the change
+ if (mDevice != value) {
+ uint32_t params = 0;
+ // check whether speaker is on
+ if (value & AudioSystem::DEVICE_OUT_SPEAKER) {
+ params |= IMediaPlayerService::kBatteryDataSpeakerOn;
+ }
+
+ int deviceWithoutSpeaker
+ = AudioSystem::DEVICE_OUT_ALL & ~AudioSystem::DEVICE_OUT_SPEAKER;
+ // check if any other device (except speaker) is on
+ if (value & deviceWithoutSpeaker ) {
+ params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
+ }
+
+ if (params != 0) {
+ addBatteryData(params);
+ }
+ }
+
// forward device change to effects that have requested to be
// aware of attached audio device.
mDevice = (uint32_t)value;
@@ -2831,6 +2867,9 @@
AudioSystem::stopOutput(thread->id(),
(AudioSystem::stream_type)mStreamType,
mSessionId);
+
+ // to track the speaker usage
+ addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
}
AudioSystem::releaseOutput(thread->id());
}
@@ -2941,6 +2980,11 @@
(AudioSystem::stream_type)mStreamType,
mSessionId);
thread->mLock.lock();
+
+ // to track the speaker usage
+ if (status == NO_ERROR) {
+ addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
+ }
}
if (status == NO_ERROR) {
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
@@ -2976,6 +3020,9 @@
(AudioSystem::stream_type)mStreamType,
mSessionId);
thread->mLock.lock();
+
+ // to track the speaker usage
+ addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
}
}
}
@@ -2995,6 +3042,9 @@
(AudioSystem::stream_type)mStreamType,
mSessionId);
thread->mLock.lock();
+
+ // to track the speaker usage
+ addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
}
}
}
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 25db25e..2fe5980 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -933,6 +933,11 @@
return -1;
}
+ // Determine whether the device is external or internal.
+ if (isExternalDevice(device)) {
+ device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
+ }
+
LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
deviceId, fd, devicePath, device->identifier.name.string(),
@@ -997,6 +1002,17 @@
android::clearKeyboardProperties(id);
}
+bool EventHub::isExternalDevice(Device* device) {
+ if (device->configuration) {
+ bool value;
+ if (device->configuration->tryGetProperty(String8("device.internal"), value)
+ && value) {
+ return false;
+ }
+ }
+ return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH;
+}
+
bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
return false;
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index f7936d2..445c04b 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -126,6 +126,9 @@
/* The input device is a joystick (implies gamepad, has joystick absolute axes). */
INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
+
+ /* The input device is external (not built-in). */
+ INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
};
/*
@@ -304,6 +307,8 @@
void setKeyboardProperties(Device* device, bool builtInKeyboard);
void clearKeyboardProperties(Device* device, bool builtInKeyboard);
+ bool isExternalDevice(Device* device);
+
// Protect all internal state.
mutable Mutex mLock;
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index c064a9c..655b672 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1572,7 +1572,7 @@
}
void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
- int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
+ int32_t eventType = POWER_MANAGER_OTHER_EVENT;
switch (eventEntry->type) {
case EventEntry::TYPE_MOTION: {
const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
@@ -1580,7 +1580,7 @@
return;
}
- if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+ if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
eventType = POWER_MANAGER_TOUCH_EVENT;
}
break;
@@ -1590,6 +1590,7 @@
if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
return;
}
+ eventType = POWER_MANAGER_BUTTON_EVENT;
break;
}
}
@@ -2304,7 +2305,7 @@
}
policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+ mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
bool needWake;
{ // acquire lock
@@ -2498,7 +2499,7 @@
}
nsecs_t eventTime = motionEvent->getEventTime();
- mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+ mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
mLock.lock();
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 304b1bb..1e118c4 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -165,14 +165,14 @@
*/
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
- /* Intercepts a generic touch, trackball or other event before queueing it.
+ /* Intercepts a touch, trackball or other motion event before queueing it.
* The policy can use this method as an opportunity to perform power management functions
* and early event preprocessing such as updating policy flags.
*
* This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
* should be dispatched to applications.
*/
- virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
+ virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
/* Allows the policy a chance to intercept a key before dispatching. */
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index c3c143c..b92c3b5 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -233,6 +233,11 @@
InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
InputDevice* device = new InputDevice(this, deviceId, name);
+ // External devices.
+ if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
+ device->setExternal(true);
+ }
+
// Switch-like devices.
if (classes & INPUT_DEVICE_CLASS_SWITCH) {
device->addMapper(new SwitchInputMapper(device));
@@ -565,7 +570,7 @@
// --- InputDevice ---
InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
- mContext(context), mId(id), mName(name), mSources(0) {
+ mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
}
InputDevice::~InputDevice() {
@@ -582,6 +587,7 @@
dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
deviceInfo.getName().string());
+ dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
@@ -985,6 +991,16 @@
downTime = mLocked.downTime;
} // release lock
+ // Key down on external an keyboard should wake the device.
+ // We don't do this for internal keyboards to prevent them from waking up in your pocket.
+ // For internal keyboards, the key layout file should specify the policy flags for
+ // each wake key individually.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ if (down && getDevice()->isExternal()
+ && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
+ policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+ }
+
if (metaStateChanged) {
getContext()->updateGlobalMetaState();
}
@@ -1379,9 +1395,18 @@
}
} // release lock
+ // Moving an external trackball or mouse should wake the device.
+ // We don't do this for internal cursor devices to prevent them from waking up
+ // the device in your pocket.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ uint32_t policyFlags = 0;
+ if (getDevice()->isExternal()) {
+ policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+ }
+
int32_t metaState = mContext->getGlobalMetaState();
int32_t pointerId = 0;
- getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
+ getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
@@ -1391,7 +1416,7 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
+ getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
}
@@ -2308,8 +2333,6 @@
}
void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
- uint32_t policyFlags = 0;
-
// Preprocess pointer data.
if (mParameters.useBadTouchFilter) {
if (applyBadTouchFilter()) {
@@ -2338,9 +2361,18 @@
savedTouch = & mCurrentTouch;
}
- // Hide the pointer on an initial down.
+ uint32_t policyFlags = 0;
if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
+ // Hide the pointer on an initial down.
getContext()->fadePointer();
+
+ // Initial downs on external touch devices should wake the device.
+ // We don't do this for internal touch screens to prevent them from waking
+ // up in your pocket.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ if (getDevice()->isExternal()) {
+ policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+ }
}
// Process touches and virtual keys.
@@ -4017,8 +4049,14 @@
axis.oldValue = axis.newValue;
}
+ // Moving a joystick axis should not wake the devide because joysticks can
+ // be fairly noisy even when not in use. On the other hand, pushing a gamepad
+ // button will likely wake the device.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ uint32_t policyFlags = 0;
+
int32_t pointerId = 0;
- getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
+ getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, &pointerId, &pointerCoords, 0, 0, 0);
}
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index b344ffe..655f0f0 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -286,6 +286,9 @@
inline const String8& getName() { return mName; }
inline uint32_t getSources() { return mSources; }
+ inline bool isExternal() { return mIsExternal; }
+ inline void setExternal(bool external) { mIsExternal = external; }
+
inline bool isIgnored() { return mMappers.isEmpty(); }
void dump(String8& dump);
@@ -317,6 +320,7 @@
String8 mName;
uint32_t mSources;
+ bool mIsExternal;
typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index 5ba1867..bb3449b 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -58,7 +58,7 @@
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
}
- virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+ virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
}
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 864241e..8404b3a 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -188,6 +188,8 @@
class FakeInputDispatcher : public InputDispatcherInterface {
public:
struct NotifyConfigurationChangedArgs {
+ NotifyConfigurationChangedArgs() : eventTime(0) { }
+
nsecs_t eventTime;
};
@@ -687,6 +689,10 @@
}
}
+ virtual bool isExternal(int32_t deviceId) const {
+ return false;
+ }
+
virtual void dump(String8& dump) {
}
};
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e6dfb7f..40417b1 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -717,6 +717,8 @@
final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
= new SparseArray<HashMap<Uri, UriPermission>>();
+ CoreSettingsObserver mCoreSettingsObserver;
+
/**
* Thread-local storage used to carry caller permissions over through
* indirect content-provider access.
@@ -3589,7 +3591,8 @@
app.instrumentationClass, app.instrumentationProfileFile,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
isRestrictedBackupMode || !normalMode,
- mConfiguration, getCommonServicesLocked());
+ mConfiguration, getCommonServicesLocked(),
+ mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, true);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
@@ -5772,6 +5775,8 @@
if (providers != null) {
mSystemThread.installSystemProviders(providers);
}
+
+ mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
}
/**
@@ -13030,4 +13035,17 @@
public void monitor() {
synchronized (this) { }
}
+
+ public void onCoreSettingsChange(Bundle settings) {
+ for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord processRecord = mLruProcesses.get(i);
+ try {
+ if (processRecord.thread != null) {
+ processRecord.thread.setCoreSettings(settings);
+ }
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/am/CoreSettingsObserver.java b/services/java/com/android/server/am/CoreSettingsObserver.java
new file mode 100644
index 0000000..25db84a
--- /dev/null
+++ b/services/java/com/android/server/am/CoreSettingsObserver.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2006-2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Helper class for watching a set of core settings which the framework
+ * propagates to application processes to avoid multiple lookups and potentially
+ * disk I/O operations. Note: This class assumes that all core settings reside
+ * in {@link Settings.Secure}.
+ */
+class CoreSettingsObserver extends ContentObserver {
+ private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName();
+
+ // mapping form property name to its type
+ private static final Map<String, Class<?>> sCoreSettingToTypeMap = new HashMap<
+ String, Class<?>>();
+ static {
+ sCoreSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
+ // add other core settings here...
+ }
+
+ private final Bundle mCoreSettings = new Bundle();
+
+ private final ActivityManagerService mActivityManagerService;
+
+ public CoreSettingsObserver(ActivityManagerService activityManagerService) {
+ super(activityManagerService.mHandler);
+ mActivityManagerService = activityManagerService;
+ beginObserveCoreSettings();
+ populateCoreSettings(mCoreSettings);
+ }
+
+ public Bundle getCoreSettingsLocked() {
+ return (Bundle) mCoreSettings.clone();
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ synchronized (mActivityManagerService) {
+ populateCoreSettings(mCoreSettings);
+ mActivityManagerService.onCoreSettingsChange(mCoreSettings);
+ }
+ }
+
+ private void beginObserveCoreSettings() {
+ for (String setting : sCoreSettingToTypeMap.keySet()) {
+ Uri uri = Settings.Secure.getUriFor(setting);
+ mActivityManagerService.mContext.getContentResolver().registerContentObserver(
+ uri, false, this);
+ }
+ }
+
+ private void populateCoreSettings(Bundle snapshot) {
+ Context context = mActivityManagerService.mContext;
+ for (Map.Entry<String, Class<?>> entry : sCoreSettingToTypeMap.entrySet()) {
+ String setting = entry.getKey();
+ Class<?> type = entry.getValue();
+ try {
+ if (type == String.class) {
+ String value = Settings.Secure.getString(context.getContentResolver(),
+ setting);
+ snapshot.putString(setting, value);
+ } else if (type == int.class) {
+ int value = Settings.Secure.getInt(context.getContentResolver(),
+ setting);
+ snapshot.putInt(setting, value);
+ } else if (type == float.class) {
+ float value = Settings.Secure.getFloat(context.getContentResolver(),
+ setting);
+ snapshot.putFloat(setting, value);
+ } else if (type == long.class) {
+ long value = Settings.Secure.getLong(context.getContentResolver(),
+ setting);
+ snapshot.putLong(setting, value);
+ }
+ } catch (SettingNotFoundException snfe) {
+ Log.w(LOG_TAG, "Cannot find setting \"" + setting + "\"", snfe);
+ }
+ }
+ }
+}
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 94c25e9..8170c61 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -102,8 +102,8 @@
private boolean mSystemReady;
private UsbAccessory mCurrentAccessory;
- // functions to restore after exiting accessory mode
- private final ArrayList<String> mAccessoryRestoreFunctions = new ArrayList<String>();
+ // USB functions that are enabled by default, to restore after exiting accessory mode
+ private final ArrayList<String> mDefaultFunctions = new ArrayList<String>();
private final Context mContext;
private final Object mLock = new Object();
@@ -118,20 +118,6 @@
boolean enteringAccessoryMode =
(mHasUsbAccessory && enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function));
- if (enteringAccessoryMode) {
- // keep a list of functions to reenable after exiting accessory mode
- mAccessoryRestoreFunctions.clear();
- int count = mEnabledFunctions.size();
- for (int i = 0; i < count; i++) {
- String f = mEnabledFunctions.get(i);
- // RNDIS should not be restored and adb is handled automatically
- if (!UsbManager.USB_FUNCTION_RNDIS.equals(f) &&
- !UsbManager.USB_FUNCTION_ADB.equals(f) &&
- !UsbManager.USB_FUNCTION_ACCESSORY.equals(f)) {
- mAccessoryRestoreFunctions.add(f);
- }
- }
- }
if (enabled) {
if (!mEnabledFunctions.contains(function)) {
mEnabledFunctions.add(function);
@@ -261,6 +247,11 @@
String functionName = files[i].getName();
if (value == 1) {
mEnabledFunctions.add(functionName);
+ // adb is enabled/disabled automatically by the adbd daemon,
+ // so don't treat it as a default function
+ if (!UsbManager.USB_FUNCTION_ADB.equals(functionName)) {
+ mDefaultFunctions.add(functionName);
+ }
} else {
mDisabledFunctions.add(functionName);
}
@@ -503,29 +494,24 @@
switch (msg.what) {
case MSG_UPDATE_STATE:
if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
- if (mConnected == 0 && mCurrentAccessory != null) {
- // turn off accessory mode when we are disconnected
+ if (mConnected == 0) {
+ // make sure accessory mode is off, and restore default functions
if (UsbManager.setFunctionEnabled(
UsbManager.USB_FUNCTION_ACCESSORY, false)) {
Log.d(TAG, "exited USB accessory mode");
- // restore previously enabled functions
- for (String function : mAccessoryRestoreFunctions) {
+ int count = mDefaultFunctions.size();
+ for (int i = 0; i < count; i++) {
+ String function = mDefaultFunctions.get(i);
if (UsbManager.setFunctionEnabled(function, true)) {
Log.e(TAG, "could not reenable function " + function);
}
}
- mAccessoryRestoreFunctions.clear();
+ }
+ if (mCurrentAccessory != null) {
mDeviceManager.accessoryDetached(mCurrentAccessory);
mCurrentAccessory = null;
-
- // this will cause an immediate reset of the USB bus,
- // so there is no point in sending the
- // function disabled broadcast.
- return;
- } else {
- Log.e(TAG, "could not disable USB_FUNCTION_ACCESSORY");
}
}
@@ -581,14 +567,18 @@
pw.print(mDisabledFunctions.get(i) + " ");
}
pw.println("");
+ pw.print(" Default Functions: ");
+ for (int i = 0; i < mDefaultFunctions.size(); i++) {
+ pw.print(mDefaultFunctions.get(i) + " ");
+ }
+ pw.println("");
pw.println(" mConnected: " + mConnected + ", mConfiguration: " + mConfiguration);
+ pw.println(" mCurrentAccessory: " + mCurrentAccessory);
pw.println(" USB Host State:");
for (String name : mDevices.keySet()) {
pw.println(" " + name + ": " + mDevices.get(name));
}
- pw.println(" mCurrentAccessory: " + mCurrentAccessory);
-
mDeviceManager.dump(fd, pw);
}
}
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index 1fcb869..a266d70 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -45,7 +45,7 @@
+ mDimSurface + ": CREATE");
try {
mDimSurface = new Surface(session, 0,
- "DimSurface",
+ "DimAnimator",
-1, 16, 16, PixelFormat.OPAQUE,
Surface.FX_SURFACE_DIM);
mDimSurface.setAlpha(0.0f);
@@ -84,7 +84,7 @@
* {@link updateSurface} after all windows are examined.
*/
void updateParameters(Resources res, WindowState w, long currentTime) {
- mDimSurface.setLayer(w.mAnimLayer-1);
+ mDimSurface.setLayer(w.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM);
final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface
@@ -177,8 +177,11 @@
return animating;
}
- public void printTo(PrintWriter pw) {
- pw.print(" mDimShown="); pw.print(mDimShown);
+ public void printTo(String prefix, PrintWriter pw) {
+ pw.print(prefix);
+ pw.print("mDimSurface="); pw.println(mDimSurface);
+ pw.print(prefix);
+ pw.print("mDimShown="); pw.print(mDimShown);
pw.print(" current="); pw.print(mDimCurrentAlpha);
pw.print(" target="); pw.print(mDimTargetAlpha);
pw.print(" delta="); pw.print(mDimDeltaPerMs);
diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java
new file mode 100644
index 0000000..084ac6f
--- /dev/null
+++ b/services/java/com/android/server/wm/DimSurface.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.graphics.PixelFormat;
+import android.util.Slog;
+import android.view.Surface;
+import android.view.SurfaceSession;
+
+import java.io.PrintWriter;
+
+class DimSurface {
+ Surface mDimSurface;
+ boolean mDimShown = false;
+ int mDimColor = 0;
+ int mLayer = -1;
+ int mLastDimWidth, mLastDimHeight;
+
+ DimSurface(SurfaceSession session) {
+ if (mDimSurface == null) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM "
+ + mDimSurface + ": CREATE");
+ try {
+ mDimSurface = new Surface(session, 0,
+ "DimSurface",
+ -1, 16, 16, PixelFormat.OPAQUE,
+ Surface.FX_SURFACE_DIM);
+ mDimSurface.setAlpha(0.0f);
+ } catch (Exception e) {
+ Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
+ }
+ }
+ }
+
+ /**
+ * Show the dim surface.
+ */
+ void show(int dw, int dh, int layer, int color) {
+ if (!mDimShown) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
+ dw + "x" + dh + ")");
+ mDimShown = true;
+ try {
+ mLastDimWidth = dw;
+ mLastDimHeight = dh;
+ mDimSurface.setPosition(0, 0);
+ mDimSurface.setSize(dw, dh);
+ mDimSurface.show();
+ } catch (RuntimeException e) {
+ Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e);
+ }
+ } else if (mLastDimWidth != dw || mLastDimHeight != dh || mDimColor != color
+ || mLayer != layer) {
+ mLastDimWidth = dw;
+ mLastDimHeight = dh;
+ mLayer = layer;
+ mDimColor = color;
+ mDimSurface.setSize(dw, dh);
+ mDimSurface.setLayer(layer);
+ mDimSurface.setAlpha(((color>>24)&0xff)/255.0f);
+ }
+ }
+
+ void hide() {
+ if (mDimShown) {
+ mDimShown = false;
+ try {
+ mDimSurface.hide();
+ } catch (RuntimeException e) {
+ Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface");
+ }
+ }
+ }
+
+ public void printTo(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("mDimSurface="); pw.println(mDimSurface);
+ pw.print(prefix); pw.print("mDimShown="); pw.print(mDimShown);
+ pw.print(" mLayer="); pw.println(mLayer);
+ pw.print(" mDimColor=0x"); pw.println(Integer.toHexString(mDimColor));
+ pw.print(prefix); pw.print("mLastDimWidth="); pw.print(mLastDimWidth);
+ pw.print(" mLastDimWidth="); pw.println(mLastDimWidth);
+ }
+}
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index 326eca7..77cec5d 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -448,7 +448,13 @@
return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
event, policyFlags, isScreenOn);
}
-
+
+ @SuppressWarnings("unused")
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+ return mWindowManagerService.mInputMonitor.interceptMotionBeforeQueueingWhenScreenOff(
+ policyFlags);
+ }
+
@SuppressWarnings("unused")
public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
KeyEvent event, int policyFlags) {
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index b1833c4..45a78af 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -258,7 +258,14 @@
KeyEvent event, int policyFlags, boolean isScreenOn) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
}
-
+
+ /* Provides an opportunity for the window manager policy to intercept early
+ * motion event processing when the screen is off since these events are normally
+ * dropped. */
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+ return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
+ }
+
/* Provides an opportunity for the window manager policy to process a key before
* ordinary dispatch. */
public boolean interceptKeyBeforeDispatching(
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 4356ce5..fbf1ec3 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -110,18 +110,16 @@
Bitmap screenshot = Surface.screenshot(0, 0);
- if (screenshot != null) {
- // Screenshot does NOT include rotation!
- mSnapshotRotation = 0;
- mWidth = screenshot.getWidth();
- mHeight = screenshot.getHeight();
- } else {
- // Just in case.
- mSnapshotRotation = display.getRotation();
- mWidth = mDisplayMetrics.widthPixels;
- mHeight = mDisplayMetrics.heightPixels;
+ if (screenshot == null) {
+ // Device is not capable of screenshots... we can't do an animation.
+ return;
}
+ // Screenshot does NOT include rotation!
+ mSnapshotRotation = 0;
+ mWidth = screenshot.getWidth();
+ mHeight = screenshot.getHeight();
+
mOriginalRotation = display.getRotation();
mOriginalWidth = mDisplayMetrics.widthPixels;
mOriginalHeight = mDisplayMetrics.heightPixels;
@@ -150,23 +148,19 @@
c = mSurface.lockCanvas(dirty);
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Unable to lock surface", e);
- return;
} catch (Surface.OutOfResourcesException e) {
Slog.w(TAG, "Unable to lock surface", e);
- return;
}
if (c == null) {
- Slog.w(TAG, "Null surface");
+ Slog.w(TAG, "Null surface canvas");
+ mSurface.destroy();
+ mSurface = null;
return;
}
- if (screenshot != null) {
- Paint paint = new Paint(0);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
- c.drawBitmap(screenshot, 0, 0, paint);
- } else {
- c.drawColor(Color.BLACK, PorterDuff.Mode.SRC);
- }
+ Paint paint = new Paint(0);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+ c.drawBitmap(screenshot, 0, 0, paint);
mSurface.unlockCanvasAndPost(c);
}
@@ -177,12 +171,14 @@
"<<< CLOSE TRANSACTION ScreenRotationAnimation");
}
- if (screenshot != null) {
- screenshot.recycle();
- }
+ screenshot.recycle();
}
}
+ boolean hasScreenshot() {
+ return mSurface != null;
+ }
+
static int deltaRotation(int oldRotation, int newRotation) {
int delta = newRotation - oldRotation;
if (delta < 0) delta += 4;
@@ -250,17 +246,14 @@
*/
public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
float animationScale) {
- // Figure out how the screen has moved from the original rotation.
- int delta = deltaRotation(mCurRotation, mOriginalRotation);
- if (false && delta == 0) {
- // Nothing changed, just remove the snapshot.
- if (mSurface != null) {
- mSurface.destroy();
- mSurface = null;
- }
+ if (mSurface == null) {
+ // Can't do animation.
return false;
}
+ // Figure out how the screen has moved from the original rotation.
+ int delta = deltaRotation(mCurRotation, mOriginalRotation);
+
switch (delta) {
case Surface.ROTATION_0:
mExitAnimation = AnimationUtils.loadAnimation(mContext,
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 15269dc..b5d84e8 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -180,6 +180,16 @@
*/
static final int WINDOW_LAYER_MULTIPLIER = 5;
+ /**
+ * Dim surface layer is immediately below target window.
+ */
+ static final int LAYER_OFFSET_DIM = 1;
+
+ /**
+ * Blur surface layer is immediately below dim layer.
+ */
+ static final int LAYER_OFFSET_BLUR = 2;
+
/** The maximum length we will accept for a loaded animation duration:
* this is 10 seconds.
*/
@@ -276,8 +286,6 @@
final IBatteryStats mBatteryStats;
- private static final boolean mInEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
-
/**
* All currently active sessions with clients.
*/
@@ -468,6 +476,7 @@
// visible behind it in case it animates in a way that would allow it to be
// seen.
WindowState mWindowDetachedWallpaper = null;
+ DimSurface mWindowAnimationBackgroundSurface = null;
int mWallpaperAnimLayerAdjustment;
float mLastWallpaperX = -1;
float mLastWallpaperY = -1;
@@ -4940,7 +4949,8 @@
if (mDisplayEnabled) {
// NOTE: We disable the rotation in the emulator because
// it doesn't support hardware OpenGL emulation yet.
- if (CUSTOM_SCREEN_ROTATION && !mInEmulator) {
+ if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
+ && mScreenRotationAnimation.hasScreenshot()) {
Surface.freezeDisplay(0);
if (!inTransaction) {
if (SHOW_TRANSACTIONS) Slog.i(TAG,
@@ -6802,6 +6812,8 @@
boolean wallpaperMayChange = false;
boolean forceHiding = false;
WindowState windowDetachedWallpaper = null;
+ WindowState windowAnimationBackground = null;
+ int windowAnimationBackgroundColor = 0;
mPolicy.beginAnimationLw(dw, dh);
@@ -6851,8 +6863,15 @@
// an animating window and take care of a request to run
// a detached wallpaper animation.
if (nowAnimating) {
- if (w.mAnimation != null && w.mAnimation.getDetachWallpaper()) {
- windowDetachedWallpaper = w;
+ if (w.mAnimation != null) {
+ if (w.mAnimation.getDetachWallpaper()) {
+ windowDetachedWallpaper = w;
+ }
+ if (w.mAnimation.getBackgroundColor() != 0) {
+ windowAnimationBackground = w;
+ windowAnimationBackgroundColor =
+ w.mAnimation.getBackgroundColor();
+ }
}
animating = true;
}
@@ -6860,9 +6879,15 @@
// If this window's app token is running a detached wallpaper
// animation, make a note so we can ensure the wallpaper is
// displayed behind it.
- if (w.mAppToken != null && w.mAppToken.animation != null
- && w.mAppToken.animation.getDetachWallpaper()) {
- windowDetachedWallpaper = w;
+ if (w.mAppToken != null && w.mAppToken.animation != null) {
+ if (w.mAppToken.animation.getDetachWallpaper()) {
+ windowDetachedWallpaper = w;
+ }
+ if (w.mAppToken.animation.getBackgroundColor() != 0) {
+ windowAnimationBackground = w;
+ windowAnimationBackgroundColor =
+ w.mAppToken.animation.getBackgroundColor();
+ }
}
if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
@@ -7301,6 +7326,17 @@
wallpaperMayChange = true;
}
+ if (windowAnimationBackgroundColor != 0) {
+ if (mWindowAnimationBackgroundSurface == null) {
+ mWindowAnimationBackgroundSurface = new DimSurface(mFxSession);
+ }
+ mWindowAnimationBackgroundSurface.show(dw, dh,
+ windowAnimationBackground.mAnimLayer - LAYER_OFFSET_DIM,
+ windowAnimationBackgroundColor);
+ } else if (mWindowAnimationBackgroundSurface != null) {
+ mWindowAnimationBackgroundSurface.hide();
+ }
+
if (wallpaperMayChange) {
if (DEBUG_WALLPAPER) Slog.v(TAG,
"Wallpaper may change! Adjusting");
@@ -7730,7 +7766,7 @@
dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
mBlurSurface.setPosition(0, 0);
mBlurSurface.setSize(dw, dh);
- mBlurSurface.setLayer(w.mAnimLayer-2);
+ mBlurSurface.setLayer(w.mAnimLayer-LAYER_OFFSET_BLUR);
if (!mBlurShown) {
try {
if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
@@ -7779,7 +7815,8 @@
// Using the same layer as Dim because they will never be shown at the
// same time. NOTE: we do NOT use mAnimLayer, because we don't
// want this surface dragged up in front of stuff that is animating.
- mBackgroundFillerSurface.setLayer(mBackgroundFillerTarget.mLayer - 1);
+ mBackgroundFillerSurface.setLayer(mBackgroundFillerTarget.mLayer
+ - LAYER_OFFSET_DIM);
mBackgroundFillerSurface.show();
} catch (RuntimeException e) {
Slog.e(TAG, "Exception showing filler surface");
@@ -8294,6 +8331,9 @@
mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
mDisplay, mFxSession, inTransaction);
}
+ if (!mScreenRotationAnimation.hasScreenshot()) {
+ Surface.freezeDisplay(0);
+ }
} else {
Surface.freezeDisplay(0);
}
@@ -8316,17 +8356,21 @@
boolean updateRotation = false;
- if (CUSTOM_SCREEN_ROTATION) {
- if (mScreenRotationAnimation != null) {
- if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
- mTransitionAnimationScale)) {
- requestAnimationLocked(0);
- } else {
- mScreenRotationAnimation = null;
- updateRotation = true;
- }
+ if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
+ && mScreenRotationAnimation.hasScreenshot()) {
+ if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
+ mTransitionAnimationScale)) {
+ requestAnimationLocked(0);
+ } else {
+ mScreenRotationAnimation = null;
+ updateRotation = true;
}
} else {
+ if (mScreenRotationAnimation != null) {
+ mScreenRotationAnimation.kill();
+ mScreenRotationAnimation = null;
+ }
+ updateRotation = true;
Surface.unfreezeDisplay(0);
}
@@ -8589,6 +8633,10 @@
if (mWindowDetachedWallpaper != null) {
pw.print(" mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper);
}
+ if (mWindowAnimationBackgroundSurface != null) {
+ pw.println(" mWindowAnimationBackgroundSurface:");
+ mWindowAnimationBackgroundSurface.printTo(" ", pw);
+ }
pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
pw.print(" mInTouchMode="); pw.print(mInTouchMode);
pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
@@ -8597,7 +8645,8 @@
pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
pw.print(" mBlurShown="); pw.println(mBlurShown);
if (mDimAnimator != null) {
- mDimAnimator.printTo(pw);
+ pw.println(" mDimAnimator:");
+ mDimAnimator.printTo(" ", pw);
} else {
pw.println( " no DimAnimator ");
}
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 5ef234a..00d0af1 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -59,6 +59,7 @@
jmethodID notifyInputChannelBroken;
jmethodID notifyANR;
jmethodID interceptKeyBeforeQueueing;
+ jmethodID interceptMotionBeforeQueueingWhenScreenOff;
jmethodID interceptKeyBeforeDispatching;
jmethodID dispatchUnhandledKey;
jmethodID checkInjectEventsPermission;
@@ -178,7 +179,7 @@
virtual nsecs_t getKeyRepeatDelay();
virtual int32_t getMaxEventsPerSecond();
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
- virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
+ virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags);
virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
@@ -215,6 +216,7 @@
} mLocked;
void updateInactivityFadeDelayLocked(const sp<PointerController>& controller);
+ void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
// Power manager interactions.
bool isScreenOn();
@@ -620,10 +622,6 @@
// - Ask the window manager what to do with normal events and trusted injected events.
// - For normal events wake and brighten the screen if currently off or dim.
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
- const int32_t WM_ACTION_PASS_TO_USER = 1;
- const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
- const int32_t WM_ACTION_GO_TO_SLEEP = 4;
-
nsecs_t when = keyEvent->getEventTime();
bool isScreenOn = this->isScreenOn();
bool isScreenBright = this->isScreenBright();
@@ -655,23 +653,13 @@
}
}
- if (wmActions & WM_ACTION_GO_TO_SLEEP) {
- android_server_PowerManagerService_goToSleep(when);
- }
-
- if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
- android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
- }
-
- if (wmActions & WM_ACTION_PASS_TO_USER) {
- policyFlags |= POLICY_FLAG_PASS_TO_USER;
- }
+ handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
} else {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
-void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
// Policy:
// - Ignore untrusted events and pass them along.
// - No special filtering for injected events required at this time.
@@ -684,12 +672,55 @@
if (!isScreenBright()) {
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
}
+ } else {
+ JNIEnv* env = jniEnv();
+ jint wmActions = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+ policyFlags);
+ if (checkAndClearExceptionFromCallback(env,
+ "interceptMotionBeforeQueueingWhenScreenOff")) {
+ wmActions = 0;
+ }
+
+ policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;
+ handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
} else {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
+void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
+ uint32_t& policyFlags) {
+ enum {
+ WM_ACTION_PASS_TO_USER = 1,
+ WM_ACTION_POKE_USER_ACTIVITY = 2,
+ WM_ACTION_GO_TO_SLEEP = 4,
+ };
+
+ if (wmActions & WM_ACTION_GO_TO_SLEEP) {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+ LOGD("handleInterceptActions: Going to sleep.");
+#endif
+ android_server_PowerManagerService_goToSleep(when);
+ }
+
+ if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+ LOGD("handleInterceptActions: Poking user activity.");
+#endif
+ android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
+ }
+
+ if (wmActions & WM_ACTION_PASS_TO_USER) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
+ } else {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+ LOGD("handleInterceptActions: Not passing key to user.");
+#endif
+ }
+}
+
bool NativeInputManager::interceptKeyBeforeDispatching(
const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) {
@@ -1204,6 +1235,10 @@
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
"interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
+ GET_METHOD_ID(gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+ gCallbacksClassInfo.clazz,
+ "interceptMotionBeforeQueueingWhenScreenOff", "(I)I");
+
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
"interceptKeyBeforeDispatching",
"(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 40882d8..554fa43 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2150,8 +2150,8 @@
sh = (!sh) ? hw_h : sh;
const size_t size = sw * sh * 4;
- LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
- sw, sh, minLayerZ, maxLayerZ);
+ //LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
+ // sw, sh, minLayerZ, maxLayerZ);
// make sure to clear all GL error flags
while ( glGetError() != GL_NO_ERROR ) ;
@@ -2236,7 +2236,7 @@
hw.compositionComplete();
- LOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
+ // LOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
return result;
}