Merge "Toggle wallpaper window flag when setting custom keyguard background" into klp-dev
diff --git a/api/current.txt b/api/current.txt
index a8b5efd..dc21e90 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10693,10 +10693,6 @@
method public int getMinFrequency();
}
- public abstract interface FlushCompleteListener {
- method public abstract void onFlushCompleted(android.hardware.Sensor);
- }
-
public class GeomagneticField {
ctor public GeomagneticField(float, float, float, long);
method public float getDeclination();
@@ -10754,6 +10750,10 @@
method public abstract void onSensorChanged(android.hardware.SensorEvent);
}
+ public abstract interface SensorEventListener2 implements android.hardware.SensorEventListener {
+ method public abstract void onFlushCompleted(android.hardware.Sensor);
+ }
+
public abstract deprecated interface SensorListener {
method public abstract void onAccuracyChanged(int, int);
method public abstract void onSensorChanged(int, float[]);
@@ -10761,7 +10761,7 @@
public abstract class SensorManager {
method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
- method public boolean flush(android.hardware.Sensor);
+ method public boolean flush(android.hardware.SensorEventListener);
method public static float getAltitude(float, float);
method public static void getAngleChange(float[], float[], float[]);
method public android.hardware.Sensor getDefaultSensor(int);
@@ -10775,9 +10775,9 @@
method public deprecated boolean registerListener(android.hardware.SensorListener, int);
method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
- method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, int, android.hardware.FlushCompleteListener);
+ method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int);
method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, android.os.Handler);
- method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, int, android.os.Handler, android.hardware.FlushCompleteListener);
+ method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
method public static boolean remapCoordinateSystem(float[], int, int, float[]);
method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
method public deprecated void unregisterListener(android.hardware.SensorListener);
diff --git a/core/java/android/hardware/FlushCompleteListener.java b/core/java/android/hardware/SensorEventListener2.java
similarity index 89%
rename from core/java/android/hardware/FlushCompleteListener.java
rename to core/java/android/hardware/SensorEventListener2.java
index fbdf4c8..4c3b429 100644
--- a/core/java/android/hardware/FlushCompleteListener.java
+++ b/core/java/android/hardware/SensorEventListener2.java
@@ -19,7 +19,7 @@
/**
* Used for receiving a notification when a flush() has been successfully completed.
*/
-public interface FlushCompleteListener {
+public interface SensorEventListener2 extends SensorEventListener {
/**
* Called after flush() is completed. This flush() could have been initiated by this application
* or some other application. All the events in the batch at the point when the flush was called
@@ -28,7 +28,7 @@
*
* @param sensor The {@link android.hardware.Sensor Sensor} on which flush was called.
*
- * @see android.hardware.SensorManager#flush(Sensor)
+ * @see android.hardware.SensorManager#flush(SensorEventListener)
*/
public void onFlushCompleted(Sensor sensor);
}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 8a4aa1d..b931313 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -533,8 +533,6 @@
*
* @see #unregisterListener(SensorEventListener)
* @see #registerListener(SensorEventListener, Sensor, int)
- *
- * @throws IllegalArgumentException when sensor is a trigger sensor.
*/
public void unregisterListener(SensorEventListener listener, Sensor sensor) {
if (listener == null || sensor == null) {
@@ -601,7 +599,6 @@
* @see #unregisterListener(SensorEventListener)
* @see #unregisterListener(SensorEventListener, Sensor)
*
- * @throws IllegalArgumentException when sensor is null or a trigger sensor
*/
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs) {
return registerListener(listener, sensor, rateUs, null);
@@ -638,7 +635,9 @@
* {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p>
*
* @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
- * that will receive the sensor events.
+ * that will receive the sensor events. If the application is interested in receiving
+ * flush complete notifications, it should register with
+ * {@link android.hardware.SensorEventListener SensorEventListener2} instead.
* @param sensor The {@link android.hardware.Sensor Sensor} to register to.
* @param rateUs The desired delay between two consecutive events in microseconds. This is only
* a hint to the system. Events may be received faster or slower than the specified
@@ -651,30 +650,23 @@
* large. If this is set to zero, batch mode is disabled and events are delivered in
* continuous mode as soon as they are available which is equivalent to calling
* {@link #registerListener(SensorEventListener, Sensor, int)}.
- * @param reservedFlags Always set to Zero.
- * @param flushCompleteListener A {@link android.hardware.FlushCompleteListener
- * FlushCompleteListener} object which is called when any application calls flush()
- * on this sensor and all the events in the batch at the time of calling flush() are
- * successfully delivered to the listeners.
- * @return true if batch mode is successfully enabled for this sensor, false otherwise.
+ * @return <code>true</code> if batch mode is successfully enabled for this sensor,
+ * <code>false</code> otherwise.
* @see #registerListener(SensorEventListener, Sensor, int)
* @see #unregisterListener(SensorEventListener)
- * @see #flush(Sensor)
- * @throws IllegalArgumentException when sensor or listener is null or a trigger sensor.
+ * @see #flush(SensorEventListener)
*/
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs,
- int maxBatchReportLatencyUs, int reservedFlags,
- FlushCompleteListener flushCompleteListener) {
+ int maxBatchReportLatencyUs) {
int delay = getDelay(rateUs);
- return registerListenerImpl(listener, sensor, delay, null, maxBatchReportLatencyUs,
- reservedFlags, flushCompleteListener);
+ return registerListenerImpl(listener, sensor, delay, null, maxBatchReportLatencyUs, 0);
}
/**
* Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given
* sensor. Events are delivered in continuous mode as soon as they are available. To reduce the
- * battery usage, use {@link #registerListener(SensorEventListener, Sensor, int, int, int,
- * FlushCompleteListener)} which enables batch mode for the sensor.
+ * battery usage, use {@link #registerListener(SensorEventListener, Sensor, int, int)} which
+ * enables batch mode for the sensor.
*
* <p class="note"></p>
* Note: Don't use this method with a one shot trigger sensor such as
@@ -706,67 +698,80 @@
* {@link android.hardware.SensorEvent sensor events} will be
* delivered to.
*
- * @return true if the sensor is supported and successfully enabled.
+ * @return <code>true</code> if the sensor is supported and successfully enabled.
*
* @see #registerListener(SensorEventListener, Sensor, int)
* @see #unregisterListener(SensorEventListener)
* @see #unregisterListener(SensorEventListener, Sensor)
- *
- * @throws IllegalArgumentException when sensor is null or a trigger sensor
*/
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs,
Handler handler) {
- if (listener == null || sensor == null) {
- return false;
- }
-
int delay = getDelay(rateUs);
- return registerListenerImpl(listener, sensor, delay, handler, 0, 0, null);
+ return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
}
/**
* Enables batch mode for a sensor with the given rate and maxBatchReportLatency.
- * @param handler
- * The {@link android.os.Handler Handler} the
- * {@link android.hardware.SensorEvent sensor events} will be
- * delivered to.
+ * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
+ * that will receive the sensor events. If the application is interested in receiving
+ * flush complete notifications, it should register with
+ * {@link android.hardware.SensorEventListener SensorEventListener2} instead.
+ * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
+ * @param rateUs The desired delay between two consecutive events in microseconds. This is only
+ * a hint to the system. Events may be received faster or slower than the specified
+ * rate. Usually events are received faster. Can be one of
+ * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
+ * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in
+ * microseconds.
+ * @param maxBatchReportLatencyUs An event in the batch can be delayed by at most
+ * maxBatchReportLatency microseconds. More events can be batched if this value is
+ * large. If this is set to zero, batch mode is disabled and events are delivered in
+ * continuous mode as soon as they are available which is equivalent to calling
+ * {@link #registerListener(SensorEventListener, Sensor, int)}.
+ * @param handler The {@link android.os.Handler Handler} the
+ * {@link android.hardware.SensorEvent sensor events} will be delivered to.
*
- * @see #registerListener(SensorEventListener, Sensor, int, int, int, FlushCompleteListener)
+ * @return <code>true</code> if batch mode is successfully enabled for this sensor,
+ * <code>false</code> otherwise.
+ * @see #registerListener(SensorEventListener, Sensor, int, int)
*/
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs,
- int maxBatchReportLatencyUs, int reservedFlags, Handler handler,
- FlushCompleteListener flushCompleteListener) {
+ int maxBatchReportLatencyUs, Handler handler) {
int delayUs = getDelay(rateUs);
- return registerListenerImpl(listener, sensor, delayUs, handler, maxBatchReportLatencyUs,
- reservedFlags, flushCompleteListener);
+ return registerListenerImpl(listener, sensor, delayUs, handler, maxBatchReportLatencyUs, 0);
}
/** @hide */
protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
- int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags,
- FlushCompleteListener flushCompleteListener);
+ int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags);
/**
- * Flushes the batch FIFO of the given sensor. If there are events in the FIFO of this sensor,
- * they are returned as if the batch timeout has expired. Events are returned in the
- * usual way through the SensorEventListener. This call doesn't effect the batch timeout for
- * this sensor. This call is asynchronous and returns immediately. FlushCompleteListener is
- * called after all the events in the batch at the time of calling this method have been
- * delivered successfully.
- * @param sensor
- * The {@link android.hardware.Sensor Sensor} to flush.
- * @return true if the flush is initiated successfully. false if the sensor isn't active
- * i.e no application is registered for updates from this sensor.
- * @see #registerListener(SensorEventListener, Sensor, int, int, int, FlushCompleteListener)
- * @throws IllegalArgumentException when sensor is null or a trigger sensor.
+ * Flushes the batch FIFO of all the sensors registered for this listener. If there are events
+ * in the FIFO of the sensor, they are returned as if the batch timeout in the FIFO of the
+ * sensors had expired. Events are returned in the usual way through the SensorEventListener.
+ * This call doesn't affect the batch timeout for this sensor. This call is asynchronous and
+ * returns immediately.
+ * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called
+ * after all the events in the batch at the time of calling this method have been delivered
+ * successfully. If the hardware doesn't support flush, it still returns true and a trivial
+ * flush complete event is sent after the current event for all the clients registered for this
+ * sensor.
+ *
+ * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object
+ * which was previously used in a registerListener call.
+ * @return <code>true</code> if the flush is initiated successfully on all the sensors
+ * registered for this listener, false if no sensor is previously registered for this
+ * listener or flush on one of the sensors fails.
+ * @see #registerListener(SensorEventListener, Sensor, int, int)
+ * @throws IllegalArgumentException when listener is null.
*/
- public boolean flush(Sensor sensor) {
- return flushImpl(sensor);
+ public boolean flush(SensorEventListener listener) {
+ return flushImpl(listener);
}
/** @hide */
- protected abstract boolean flushImpl(Sensor sensor);
+ protected abstract boolean flushImpl(SensorEventListener listener);
/**
* <p>
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 9747f0d..14f67c5 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -93,17 +93,20 @@
/** @hide */
@Override
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
- int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags,
- FlushCompleteListener flushCompleteListener) {
- if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
- if (listener == null) throw new IllegalArgumentException("listener cannot be null");
- if (reservedFlags != 0) throw new IllegalArgumentException("reservedFlags should be zero");
- if (delayUs < 0) throw new IllegalArgumentException("rateUs should be positive");
- if (maxBatchReportLatencyUs < 0)
- throw new IllegalArgumentException("maxBatchReportLatencyUs should be positive");
+ int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
+ if (listener == null || sensor == null) {
+ Log.e(TAG, "sensor or listener is null");
+ return false;
+ }
// Trigger Sensors should use the requestTriggerSensor call.
- if (Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT)
- throw new IllegalArgumentException("Trigger Sensors cannot use registerListener");
+ if (Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT) {
+ Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
+ return false;
+ }
+ if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
+ Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
+ return false;
+ }
// Invariants to preserve:
// - one Looper per SensorEventListener
@@ -113,7 +116,7 @@
SensorEventQueue queue = mSensorListeners.get(listener);
if (queue == null) {
Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
- queue = new SensorEventQueue(listener, looper, this, flushCompleteListener);
+ queue = new SensorEventQueue(listener, looper, this);
if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) {
queue.dispose();
return false;
@@ -200,16 +203,17 @@
}
}
- protected boolean flushImpl(Sensor sensor) {
- if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
- if(Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT)
- throw new IllegalArgumentException("Trigger Sensors cannot call flush");
+ protected boolean flushImpl(SensorEventListener listener) {
+ if (listener == null) throw new IllegalArgumentException("listener cannot be null");
- FlushEventQueue queue = new FlushEventQueue(mMainLooper, this);
- if (queue.flushSensor(sensor) != 0) {
- return false;
+ synchronized (mSensorListeners) {
+ SensorEventQueue queue = mSensorListeners.get(listener);
+ if (queue == null) {
+ return false;
+ } else {
+ return (queue.flush() == 0);
+ }
}
- return true;
}
/*
@@ -224,7 +228,7 @@
int maxBatchReportLatencyUs, int reservedFlags);
private static native int nativeDisableSensor(int eventQ, int handle);
private static native void nativeDestroySensorEventQueue(int eventQ);
- private static native int nativeFlushSensor(int eventQ, int handle);
+ private static native int nativeFlushSensor(int eventQ);
private int nSensorEventQueue;
private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
@@ -291,10 +295,9 @@
return false;
}
- public int flushSensor(Sensor sensor) {
+ public int flush() {
if (nSensorEventQueue == 0) throw new NullPointerException();
- if (sensor == null) throw new NullPointerException();
- return nativeFlushSensor(nSensorEventQueue, sensor.getHandle());
+ return nativeFlushSensor(nSensorEventQueue);
}
public boolean hasSensors() {
@@ -347,14 +350,12 @@
static final class SensorEventQueue extends BaseEventQueue {
private final SensorEventListener mListener;
- private final FlushCompleteListener mFlushCompleteListener;
private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
public SensorEventQueue(SensorEventListener listener, Looper looper,
- SystemSensorManager manager, FlushCompleteListener flushCompleteListener) {
+ SystemSensorManager manager) {
super(looper, manager);
mListener = listener;
- mFlushCompleteListener = flushCompleteListener;
}
public void addSensorEvent(Sensor sensor) {
@@ -408,9 +409,9 @@
@SuppressWarnings("unused")
protected void dispatchFlushCompleteEvent(int handle) {
- final Sensor sensor = sHandleToSensor.get(handle);
- if (mFlushCompleteListener != null) {
- mFlushCompleteListener.onFlushCompleted(sensor);
+ if (mListener instanceof SensorEventListener2) {
+ final Sensor sensor = sHandleToSensor.get(handle);
+ ((SensorEventListener2)mListener).onFlushCompleted(sensor);
}
return;
}
@@ -464,30 +465,4 @@
protected void dispatchFlushCompleteEvent(int handle) {
}
}
-
- static final class FlushEventQueue extends BaseEventQueue {
- public FlushEventQueue(Looper looper, SystemSensorManager manager) {
- super(looper, manager);
- }
-
- @SuppressWarnings("unused")
- @Override
- protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
- long timestamp) {
- }
-
- @Override
- @SuppressWarnings("unused")
- protected void addSensorEvent(Sensor sensor) {
- }
-
- @Override
- @SuppressWarnings("unused")
- protected void removeSensorEvent(Sensor sensor) {
- }
-
- @SuppressWarnings("unused")
- protected void dispatchFlushCompleteEvent(int handle) {
- }
- }
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 23ed019..44e7ec1 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -160,8 +160,7 @@
public View getItemView(final MenuItemImpl item, View convertView, ViewGroup parent) {
View actionView = item.getActionView();
if (actionView == null || item.hasCollapsibleActionView()) {
- // Don't recycle existing item views for action buttons; it interferes with transitions.
- actionView = super.getItemView(item, null, parent);
+ actionView = super.getItemView(item, convertView, parent);
}
actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java
index ccedf63..071193c 100644
--- a/core/java/com/android/internal/widget/SubtitleView.java
+++ b/core/java/com/android/internal/widget/SubtitleView.java
@@ -180,7 +180,9 @@
mInnerPaddingX = (int) (size * INNER_PADDING_RATIO + 0.5f);
mHasMeasurements = false;
- forceLayout();
+
+ requestLayout();
+ invalidate();
}
}
@@ -189,7 +191,9 @@
mTextPaint.setTypeface(typeface);
mHasMeasurements = false;
- forceLayout();
+
+ requestLayout();
+ invalidate();
}
}
@@ -198,7 +202,9 @@
mAlignment = textAlignment;
mHasMeasurements = false;
- forceLayout();
+
+ requestLayout();
+ invalidate();
}
}
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 4290a6e..793d1bf 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -220,9 +220,9 @@
receiver->decStrong((void*)nativeInitSensorEventQueue);
}
-static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) {
+static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jint eventQ) {
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
- return receiver->getSensorEventQueue()->flushSensor(handle);
+ return receiver->getSensorEventQueue()->flush();
}
//----------------------------------------------------------------------------
@@ -255,7 +255,7 @@
(void*)nativeDestroySensorEventQueue },
{"nativeFlushSensor",
- "(II)I",
+ "(I)I",
(void*)nativeFlushSensor },
};
diff --git a/docs/html/distribute/googleplay/spotlight/games.jd b/docs/html/distribute/googleplay/spotlight/games.jd
index 4e356db..1fbc03f 100644
--- a/docs/html/distribute/googleplay/spotlight/games.jd
+++ b/docs/html/distribute/googleplay/spotlight/games.jd
@@ -102,7 +102,7 @@
width: 78px;
float: left;
margin: 12px 20px 30px 20px;"
- src="//lh5.ggpht.com/l20dR2HYLV8vECoC35q_0NdfaAGTe4lZIFy_wCJRDqZjeQqSgneLRpXi3qOnnCaLXA=w124">
+ src="//lh4.ggpht.com/Q7mQJsdhulW4_s039R9aaRhQkGnyzLkhF00j5EnyhHOivijnyi7P7b5A8qG0xk1r-jQ=w124">
<div style="list-style: none;height:100%;
float: right;
diff --git a/docs/html/distribute/googleplay/spotlight/tablets.jd b/docs/html/distribute/googleplay/spotlight/tablets.jd
index cfea29a..7a98755 100644
--- a/docs/html/distribute/googleplay/spotlight/tablets.jd
+++ b/docs/html/distribute/googleplay/spotlight/tablets.jd
@@ -17,7 +17,90 @@
expand their offering to include Android tablets.</p>
-<div style="margin-bottom:2em;"><!-- START STORY -->
+<div style="margin-bottom:2em;" id="rememberthemilk"><!-- START STORY -->
+
+<h3>Remember The Milk: Lifting installs with tablet design</h3>
+
+ <img alt="" class="screenshot thumbnail" style="-webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px height:78px;
+ width: 78px;
+ float: left;
+ margin: 12px 20px 9px 20px;" src=
+ "//lh3.ggpht.com/xmnal18taauP2mjQFEhr1PhcItQ_W32IRuaD86IoL2U_4E-mfeKiliKtkISgOuA6Ln9n=w124">
+
+ <div style="list-style: none;height:100%;
+ float: right;
+ border-top: 1px solid #9C0;
+ width: 220px;
+ margin: 4px 20px;padding: .5em;">
+
+
+ <h5>About the app</h5>
+
+
+ <ul>
+ <li><a href="//play.google.com/store/apps/details?id=com.rememberthemilk.MobileRTM">Remember The Milk</a></li>
+ <li>A feature-packed to-do list app; never forget the milk (or anything else) again</li>
+ </ul>
+
+ <h5>Tablet Results</h5>
+
+ <ul>
+ <li>83% jump in tablet installs following update </li>
+ <li>Nexus 7 is most popular Android device for app </li>
+ <li>Single APK for phones and tablets</li>
+ </ul>
+
+ <div style="padding:.5em 0 0 1em;">
+ <a href="//play.google.com/store/apps/details?id=com.rememberthemilk.MobileRTM">
+ <img alt="Android app on Google Play"
+ src="//developer.android.com/images/brand/en_generic_rgb_wo_45.png" />
+ </a>
+
+ </div>
+ </div>
+
+ <div style="line-height:1.4em;">
+ <p style="margin-top:0;margin-bottom:12px;">When the Android tablet guidelines
+ came out in 2012, the team at Remember The Milk had already been thinking about
+ a redesign for their <a href="//play.google.com/store/apps/details?id=com.rememberthemilk.MobileRTM">feature-packed
+ to-do list app</a>. Omar Kilani, Co-founder of Remember The Milk, explains how
+ <a href="//blog.rememberthemilk.com/2013/04/the-all-new-remember-the-milk-for-android-and-tablets-too/">updating</a>
+ their app to meet the tablet guidelines lead to an 83% jump in tablet installs: </p>
+
+ <p>“We took this as an opportunity to think about how we were going to approach
+ Android tablets differently from a user experience perspective. The guidelines
+ were a helpful resource, and with the extra screen real estate tablets afford,
+ users have the opportunity to see all of their data in context and drill down
+ on more items. All of this is accomplished using a single APK on Play, even though
+ the phone and tablet versions each capture completely different use cases for us.”</p>
+
+ <p>“In the month after updating, we saw our tablet installs on Google Play jump 83%,
+ and the Nexus 7 is now the most popular Android device amongst our users. For us,
+ designing for tablets was an investment that has really paid off.”</p>
+
+ <p>The team also came out with a number of other goodies — including a new set of
+ widgets and richer notifications, and more ways to provide an immersive experience
+ for their users.</p>
+ </div>
+
+ <div style="clear:both;margin-top:30px;width:auto;">
+
+ <img src="{@docRoot}images/distribute/rememberthemilk.png">
+
+ <div style="width:600px;margin-top:0px;padding:0 90px;">
+ <p class="image-caption"><span style="font-weight:500;">Tablet redesign led to lift
+ in installs</span>: Following the redesign of the Android app, in part to meet the tablet
+ design criteria, Remember The Milk saw an 83% increase in tablet installs.</p>
+ </div>
+
+ </div>
+
+</div> <!-- END STORY -->
+
+
+<div style="margin-bottom:2em;" id="mint"><!-- START STORY -->
<h3>Mint: More screen real estate = more engagement</h3>
@@ -96,7 +179,7 @@
<div style="clear:both;margin-top:40px;width:auto;">
- <a href=""><img src="{@docRoot}images/distribute/mint.png"></a>
+ <img src="{@docRoot}images/distribute/mint.png">
<div style="width:600px;margin-top:0px;padding:0 90px;">
<p class="image-caption"><span style="font-weight:500;">Making the most of tablet screens</span>: Mint used the extra screen area on tablets to offer quick access to additional tools and information.</p>
@@ -184,7 +267,7 @@
<div style="clear:both;margin-top:40px;width:auto;">
- <a href=""><img src="{@docRoot}images/distribute/tinyvillage.png"></a>
+ <img src="{@docRoot}images/distribute/tinyvillage.png">
<div style="width:600px;margin-top:0px;padding:0 90px;">
<p class="image-caption"><span style="font-weight:500;">More monetization
@@ -268,7 +351,7 @@
<div style="clear:both;margin-top:40px;width:auto;">
- <a href=""><img src="{@docRoot}images/distribute/instapaper.png"></a>
+ <img src="{@docRoot}images/distribute/instapaper.png">
<div style="width:600px;margin-top:0px;padding:0 90px;">
<p class="image-caption"><span style="font-weight:500;">Popular with
diff --git a/docs/html/images/distribute/rememberthemilk.png b/docs/html/images/distribute/rememberthemilk.png
new file mode 100644
index 0000000..b170cf3
--- /dev/null
+++ b/docs/html/images/distribute/rememberthemilk.png
Binary files differ
diff --git a/docs/html/training/articles/security-tips.jd b/docs/html/training/articles/security-tips.jd
index 1ac56b9..54aebac 100644
--- a/docs/html/training/articles/security-tips.jd
+++ b/docs/html/training/articles/security-tips.jd
@@ -553,7 +553,7 @@
or an explicit intent to a specific application component.</p>
<p>Note that ordered broadcasts can be “consumed” by a recipient, so they
-may not be delivered to all applications. If you are sending an intent that muse be delivered
+may not be delivered to all applications. If you are sending an intent that must be delivered
to a specific receiver, then you must use an explicit intent that declares the receiver
by nameintent.</p>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
index d1862cd..7039218 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
@@ -17,12 +17,14 @@
import android.os.Handler;
import android.os.Looper;
+import android.util.Log;
import android.view.View;
public class KeyguardViewStateManager implements
SlidingChallengeLayout.OnChallengeScrolledListener,
ChallengeLayout.OnBouncerStateChangedListener {
+ private static final String TAG = "KeyguardViewStateManager";
private KeyguardWidgetPager mKeyguardWidgetPager;
private ChallengeLayout mChallengeLayout;
private KeyguardHostView mKeyguardHostView;
@@ -100,18 +102,20 @@
}
public void fadeOutSecurity(int duration) {
- ((View) mKeyguardSecurityContainer).animate().alpha(0).setDuration(duration);
+ ((View) mKeyguardSecurityContainer).animate().alpha(0f).setDuration(duration).start();
}
public void fadeInSecurity(int duration) {
- ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration);
+ ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration).start();
}
public void onPageBeginMoving() {
if (mChallengeLayout.isChallengeOverlapping() &&
mChallengeLayout instanceof SlidingChallengeLayout) {
SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
- scl.fadeOutChallenge();
+ if (!mKeyguardWidgetPager.isWarping()) {
+ scl.fadeOutChallenge();
+ }
mPageIndexOnPageBeginMoving = mKeyguardWidgetPager.getCurrentPage();
}
// We use mAppWidgetToShow to show a particular widget after you add it--
@@ -133,7 +137,9 @@
public void onPageSwitching(View newPage, int newPageIndex) {
if (mKeyguardWidgetPager != null && mChallengeLayout instanceof SlidingChallengeLayout) {
boolean isCameraPage = newPage instanceof CameraWidgetFrame;
- ((SlidingChallengeLayout) mChallengeLayout).setChallengeInteractive(!isCameraPage);
+ SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
+ scl.setChallengeInteractive(!isCameraPage);
+ if (isCameraPage) scl.fadeOutChallenge();
}
// If the page we're settling to is the same as we started on, and the action of
@@ -174,13 +180,15 @@
}
public void onPageBeginWarp() {
- // fadeOutSecurity(WARP_FADE_DURATION);
- // mKeyguardWidgetPager.showNonWarpViews(WARP_FADE_DURATION, false);
+ fadeOutSecurity(SlidingChallengeLayout.CHALLENGE_FADE_OUT_DURATION);
+ View frame = mKeyguardWidgetPager.getPageAt(mKeyguardWidgetPager.getPageWarpIndex());
+ ((KeyguardWidgetFrame)frame).showFrame(this);
}
public void onPageEndWarp() {
- // fadeInSecurity(WARP_FADE_DURATION);
- // mKeyguardWidgetPager.showNonWarpViews(WARP_FADE_DURATION, true);
+ fadeInSecurity(SlidingChallengeLayout.CHALLENGE_FADE_IN_DURATION);
+ View frame = mKeyguardWidgetPager.getPageAt(mKeyguardWidgetPager.getPageWarpIndex());
+ ((KeyguardWidgetFrame)frame).hideFrame(this);
}
private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
index f8857ab..704af6e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java
@@ -188,11 +188,13 @@
@Override
public void onPageBeginWarp() {
+ showOutlinesAndSidePages();
mViewStateManager.onPageBeginWarp();
}
@Override
public void onPageEndWarp() {
+ hideOutlinesAndSidePages();
mViewStateManager.onPageEndWarp();
}
@@ -495,7 +497,7 @@
}
public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
- if (getPageWarpIndex() != -1) {
+ if (isWarping()) {
return index == getPageWarpIndex() ? 1.0f : 0.0f;
}
if (showSidePages) {
@@ -949,17 +951,17 @@
// to keep event dispatch happy.
mCameraEventInProgress = true;
userActivity();
- startWarp(cameraPage);
+ startPageWarp(cameraPage);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mCameraEventInProgress = false;
- endWarp = true;
+ endWarp = isWarping();
break;
}
dispatchTouchEvent(event);
// This has to happen after the event has been handled by the real widget pager
- if (endWarp) endWarp();
+ if (endWarp) stopPageWarp();
}
endCameraEvent();
}
diff --git a/packages/Keyguard/src/com/android/keyguard/PagedView.java b/packages/Keyguard/src/com/android/keyguard/PagedView.java
index 666227c..6cf6953 100644
--- a/packages/Keyguard/src/com/android/keyguard/PagedView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PagedView.java
@@ -47,6 +47,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
@@ -60,12 +61,13 @@
* sequential list of "pages"
*/
public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener {
+ private static final int WARP_SNAP_DURATION = 160;
private static final String TAG = "WidgetPagedView";
private static final boolean DEBUG = false;
private static final boolean DEBUG_WARP = false;
protected static final int INVALID_PAGE = -1;
- private static final int WARP_PEEK_ANIMATION_DURATION = 250;
- private static final float WARP_ANIMATE_AMOUNT = -40.0f; // in dip
+ private static final int WARP_PEEK_ANIMATION_DURATION = 150;
+ private static final float WARP_ANIMATE_AMOUNT = -75.0f; // in dip
// the min drag distance for a fling to register, to prevent random page shifts
private static final int MIN_LENGTH_FOR_FLING = 25;
@@ -261,6 +263,8 @@
private boolean mIsCameraEvent;
private float mWarpPeekAmount;
+ private boolean mAnimatingWarp; // true while warped page is being animated
+ private boolean mFingerDown;
public interface PageSwitchListener {
void onPageSwitching(View newPage, int newPageIndex);
@@ -484,7 +488,7 @@
if (DEBUG_WARP) Log.v(TAG, "pageBeginMoving(" + mIsPageMoving + ")");
if (!mIsPageMoving) {
mIsPageMoving = true;
- if (mPageWarpIndex != -1) {
+ if (isWarping()) {
onPageBeginWarp();
if (mPageSwapIndex != -1) {
swapPages(mPageSwapIndex, mPageWarpIndex);
@@ -498,12 +502,12 @@
if (DEBUG_WARP) Log.v(TAG, "pageEndMoving(" + mIsPageMoving + ")");
if (mIsPageMoving) {
mIsPageMoving = false;
- if (mPageWarpIndex != -1) {
+ if (isWarping()) {
if (mPageSwapIndex != -1) {
swapPages(mPageSwapIndex, mPageWarpIndex);
- resetPageWarp();
}
onPageEndWarp();
+ resetPageWarp();
}
onPageEndMoving();
}
@@ -1124,8 +1128,8 @@
}
case MotionEvent.ACTION_DOWN: {
- if (mIsCameraEvent) {
- animateWarpPageOnScreen();
+ if (mIsCameraEvent && !mAnimatingWarp) {
+ animateWarpPageOnScreen("interceptTouch(): DOWN");
}
// Remember where the motion event started
saveDownState(ev);
@@ -1219,6 +1223,8 @@
mTotalMotionX = 0;
mActivePointerId = ev.getPointerId(0);
+ mFingerDown = true;
+
// Determine if the down event is within the threshold to be an edge swipe
int leftEdgeBoundary = getViewportOffsetX() + mEdgeSwipeRegionSize;
int rightEdgeBoundary = getMeasuredWidth() - getViewportOffsetX() - mEdgeSwipeRegionSize;
@@ -1393,8 +1399,10 @@
if (mTouchState == TOUCH_STATE_SCROLLING) {
pageBeginMoving();
- } else {
- animateWarpPageOnScreen();
+ }
+
+ if (mIsCameraEvent && !mAnimatingWarp) {
+ animateWarpPageOnScreen("onTouch(): DOWN");
}
break;
@@ -1571,7 +1579,8 @@
// move to the left and fling to the right will register as a fling to the right.
if (((isSignificantMove && deltaX > 0 && !isFling) ||
(isFling && velocityX > 0)) && mCurrentPage > 0) {
- finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage - 1;
+ finalPage = returnToOriginalPage || isWarping()
+ ? mCurrentPage : mCurrentPage - 1;
snapToPageWithVelocity(finalPage, velocityX);
} else if (((isSignificantMove && deltaX < 0 && !isFling) ||
(isFling && velocityX < 0)) &&
@@ -1661,6 +1670,7 @@
setTouchState(TOUCH_STATE_REST);
mActivePointerId = INVALID_POINTER;
mDownEventOnEdge = false;
+ mFingerDown = false;
}
protected void onUnhandledTap(MotionEvent ev) {}
@@ -1790,7 +1800,14 @@
}
protected void snapToDestination() {
- snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION);
+ if (isWarping()) {
+ cancelWarpAnimation("snapToDestination");
+ }
+ snapToPage(getPageNearestToCenterOfScreen(), getPageSnapDuration());
+ }
+
+ private int getPageSnapDuration() {
+ return isWarping() ? WARP_SNAP_DURATION : PAGE_SNAP_ANIMATION_DURATION;
}
private static class ScrollInterpolator implements Interpolator {
@@ -1817,6 +1834,10 @@
whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
int halfScreenSize = getViewportWidth() / 2;
+ if (isWarping()) {
+ cancelWarpAnimation("snapToPageWithVelocity");
+ }
+
if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
if (DEBUG) Log.d(TAG, "snapToPageWithVelocity.getRelativeChildOffset(): "
+ getViewportWidth() + ", " + getChildWidth(whichPage));
@@ -1827,7 +1848,7 @@
if (Math.abs(velocity) < mMinFlingVelocity) {
// If the velocity is low enough, then treat this more as an automatic page advance
// as opposed to an apparent physical response to flinging
- snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+ snapToPage(whichPage, getPageSnapDuration());
return;
}
@@ -1851,10 +1872,10 @@
}
protected void snapToPage(int whichPage) {
- snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+ snapToPage(whichPage, getPageSnapDuration());
}
protected void snapToPageImmediately(int whichPage) {
- snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true);
+ snapToPage(whichPage, getPageSnapDuration(), true);
}
protected void snapToPage(int whichPage, int duration) {
@@ -1884,8 +1905,8 @@
mNextPage = whichPage;
}
- if (mPageWarpIndex != -1) {
- animateWarpPageOffScreen();
+ if (isWarping()) {
+ onPageEndWarp();
resetPageWarp();
}
@@ -1918,6 +1939,10 @@
invalidate();
}
+ protected boolean isWarping() {
+ return mPageWarpIndex != -1;
+ }
+
public void scrollLeft() {
if (mScroller.isFinished()) {
if (mCurrentPage > 0) snapToPage(mCurrentPage - 1);
@@ -2650,21 +2675,53 @@
mIsCameraEvent = false;
}
- private void animateWarpPageOnScreen() {
- if (DEBUG_WARP) Log.v(TAG, "animateWarpPageOnScreen()");
- if (mPageWarpIndex != -1) {
+ AnimatorListenerAdapter mFinishWarpAnimationListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimatingWarp = false;
+ if (!mFingerDown) {
+ animateWarpPageOffScreen("animation end", true);
+ }
+ }
+ };
+
+ private void cancelWarpAnimation(String msg) {
+ if (DEBUG_WARP) Log.v(TAG, "cancelWarpAnimation(" + msg + ")");
+ // We're done with the animation, let the scroller take over the positioning
+ KeyguardWidgetFrame v = (KeyguardWidgetFrame) getPageAt(mPageWarpIndex);
+ v.animate().cancel();
+ v.setTranslationX(0f);
+ scrollBy((int) Math.round(v.getTranslationX() - mWarpPeekAmount), 0);
+ }
+
+ private void animateWarpPageOnScreen(String reason) {
+ if (DEBUG_WARP) Log.v(TAG, "animateWarpPageOnScreen(" + reason + ")");
+ if (isWarping()) {
+ onPageBeginWarp();
KeyguardWidgetFrame v = (KeyguardWidgetFrame) getPageAt(mPageWarpIndex);
if (DEBUG_WARP) Log.v(TAG, "moving page on screen: Tx=" + v.getTranslationX());
- v.animate().translationX(mWarpPeekAmount).setDuration(WARP_PEEK_ANIMATION_DURATION);
+ DecelerateInterpolator interp = new DecelerateInterpolator(1.5f);
+ v.animate().translationX(mWarpPeekAmount)
+ .setInterpolator(interp)
+ .setDuration(WARP_PEEK_ANIMATION_DURATION)
+ .setListener(mFinishWarpAnimationListener);
+ mAnimatingWarp = true;
}
}
- private void animateWarpPageOffScreen() {
- if (DEBUG_WARP) Log.v(TAG, "animateWarpPageOffScreen()");
- if (mPageWarpIndex != -1) {
+ private void animateWarpPageOffScreen(String reason, boolean animate) {
+ if (DEBUG_WARP) Log.v(TAG, "animateWarpPageOffScreen(" + reason + " anim:" + animate + ")");
+ if (isWarping()) {
+ onPageEndWarp();
KeyguardWidgetFrame v = (KeyguardWidgetFrame) getPageAt(mPageWarpIndex);
if (DEBUG_WARP) Log.v(TAG, "moving page off screen: Tx=" + v.getTranslationX());
- v.animate().translationX(0.0f).setDuration(WARP_PEEK_ANIMATION_DURATION);
+ AccelerateInterpolator interp = new AccelerateInterpolator(1.5f);
+ v.animate().translationX(0.0f)
+ .setInterpolator(interp)
+ .setDuration(animate ? WARP_PEEK_ANIMATION_DURATION : 0)
+ .setListener(null);
+ } else {
+ if (DEBUG_WARP) Log.e(TAG, "animateWarpPageOffScreen(): not warping", new Exception());
}
}
@@ -2681,7 +2738,7 @@
}
}
- public void startWarp(int pageIndex) {
+ public void startPageWarp(int pageIndex) {
if (DEBUG_WARP) Log.v(TAG, "START WARP");
if (pageIndex != mCurrentPage + 1) {
mPageSwapIndex = mCurrentPage + 1;
@@ -2693,7 +2750,7 @@
return mPageWarpIndex;
}
- public void endWarp() {
+ public void stopPageWarp() {
if (DEBUG_WARP) Log.v(TAG, "END WARP");
// mPageSwapIndex is reset in snapToPage() after the scroll animation completes
}
diff --git a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
index 5e7816c..1036c83 100644
--- a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
+++ b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
@@ -88,8 +88,8 @@
public static final int SCROLL_STATE_SETTLING = 2;
public static final int SCROLL_STATE_FADING = 3;
- private static final int CHALLENGE_FADE_OUT_DURATION = 100;
- private static final int CHALLENGE_FADE_IN_DURATION = 160;
+ public static final int CHALLENGE_FADE_OUT_DURATION = 100;
+ public static final int CHALLENGE_FADE_IN_DURATION = 160;
private static final int MAX_SETTLE_DURATION = 600; // ms
diff --git a/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml b/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
index 98b5cfe..d503216 100644
--- a/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
+++ b/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
@@ -15,9 +15,12 @@
-->
<com.android.printspooler.PrintDialogFrame xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/content_container"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:background="@color/container_background">
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <FrameLayout
+ android:id="@+id/content_container"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/container_background">
+ </FrameLayout>
</com.android.printspooler.PrintDialogFrame>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintDialogFrame.java b/packages/PrintSpooler/src/com/android/printspooler/PrintDialogFrame.java
index 6dd8aa0a..c1c4d21 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintDialogFrame.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintDialogFrame.java
@@ -24,6 +24,8 @@
public final int mMaxWidth;
+ public int mHeight;
+
public PrintDialogFrame(Context context, AttributeSet attrs) {
super(context, attrs);
mMaxWidth = context.getResources().getDimensionPixelSize(
@@ -32,13 +34,36 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- if (widthMode == MeasureSpec.AT_MOST) {
- final int receivedWidth = MeasureSpec.getSize(widthMeasureSpec);
- final int computedWidth = Math.min(mMaxWidth, receivedWidth);
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(computedWidth,
- MeasureSpec.EXACTLY);
- }
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int measuredWidth = getMeasuredWidth();
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ switch (widthMode) {
+ case MeasureSpec.UNSPECIFIED: {
+ measuredWidth = mMaxWidth;
+ } break;
+
+ case MeasureSpec.AT_MOST: {
+ final int receivedWidth = MeasureSpec.getSize(widthMeasureSpec);
+ measuredWidth = Math.min(mMaxWidth, receivedWidth);
+ } break;
+ }
+
+ mHeight = Math.max(mHeight, getMeasuredHeight());
+
+ int measuredHeight = getMeasuredHeight();
+ final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ switch (heightMode) {
+ case MeasureSpec.UNSPECIFIED: {
+ measuredHeight = mHeight;
+ } break;
+
+ case MeasureSpec.AT_MOST: {
+ final int receivedHeight = MeasureSpec.getSize(heightMeasureSpec);
+ measuredHeight = Math.min(mHeight, receivedHeight);
+ } break;
+ }
+
+ setMeasuredDimension(measuredWidth, measuredHeight);
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index d6ebc2d..2922dd1 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -59,12 +59,14 @@
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
+import android.view.ViewGroup.LayoutParams;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
@@ -75,6 +77,7 @@
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
@@ -1409,7 +1412,9 @@
postSwitchCallback.run();
}
}
- });
+ },
+ new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
} break;
}
} break;
@@ -1426,7 +1431,9 @@
postSwitchCallback.run();
}
}
- });
+ },
+ new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER));
} break;
}
} break;
@@ -1474,7 +1481,8 @@
getLayoutInflater().inflate(showLayoutId, contentContainer, true);
}
- private void animateUiSwitch(int showLayoutId, final Runnable postAnimateCommand) {
+ private void animateUiSwitch(int showLayoutId, final Runnable postAnimateCommand,
+ final LayoutParams containerParams) {
// Find everything we will shuffle around.
final ViewGroup contentContainer = (ViewGroup) findViewById(R.id.content_container);
final View hidingView = contentContainer.getChildAt(0);
@@ -1511,6 +1519,8 @@
contentContainer.setScaleY(1.0f);
contentContainer.addView(showingView);
+ contentContainer.setLayoutParams(containerParams);
+
// Third animation - show the new content.
AutoCancellingAnimator.animate(showingView).withLayer().alpha(1.0f)
.withEndAction(new Runnable() {
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index a6375e1..50a7b5c 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -473,11 +473,11 @@
current.setDataPosition(0);
ProcessStats stats = ProcessStats.CREATOR.createFromParcel(current);
current.recycle();
- int i = 0;
- while (i < files.size() && (stats.mTimePeriodEndRealtime
+ int i = files.size()-1;
+ while (i >= 0 && (stats.mTimePeriodEndRealtime
- stats.mTimePeriodStartRealtime) < minTime) {
AtomicFile file = new AtomicFile(new File(files.get(i)));
- i++;
+ i--;
ProcessStats moreStats = new ProcessStats(false);
readLocked(moreStats, file);
if (moreStats.mReadError == null) {
@@ -490,7 +490,7 @@
- moreStats.mTimePeriodStartRealtime, sb);
Slog.i(TAG, sb.toString());
} else {
- Slog.w(TAG, "Failure reading " + files.get(i-1) + "; "
+ Slog.w(TAG, "Failure reading " + files.get(i+1) + "; "
+ moreStats.mReadError);
continue;
}