Merge "Support for writing output data to a provided callback function instead of a file"
diff --git a/api/current.txt b/api/current.txt
index f6bfd73..90890d6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21426,7 +21426,6 @@
field public static final int AXIS_Y = 1; // 0x1
field public static final int AXIS_Z = 11; // 0xb
field public static final int BUTTON_BACK = 8; // 0x8
- field public static final int BUTTON_ERASER = 32; // 0x20
field public static final int BUTTON_FORWARD = 16; // 0x10
field public static final int BUTTON_PRIMARY = 1; // 0x1
field public static final int BUTTON_SECONDARY = 2; // 0x2
@@ -22011,6 +22010,7 @@
method public void setOnDragListener(android.view.View.OnDragListener);
method public void setOnFocusChangeListener(android.view.View.OnFocusChangeListener);
method public void setOnGenericMotionListener(android.view.View.OnGenericMotionListener);
+ method public void setOnHoverListener(android.view.View.OnHoverListener);
method public void setOnKeyListener(android.view.View.OnKeyListener);
method public void setOnLongClickListener(android.view.View.OnLongClickListener);
method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 02faf49..0933193 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -24,6 +24,8 @@
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.DataUsageFeedback;
import android.text.TextUtils;
/**
@@ -204,7 +206,44 @@
}
if ((ci != null) && (ci.person_id > 0)) {
- ContactsContract.Contacts.markAsContacted(resolver, ci.person_id);
+ // Update usage information for the number associated with the contact ID.
+ // We need to use both the number and the ID for obtaining a data ID since other
+ // contacts may have the same number.
+
+ final Cursor cursor;
+
+ // We should prefer normalized one (probably coming from
+ // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
+ if (ci.normalizedNumber != null) {
+ final String normalizedPhoneNumber = ci.normalizedNumber;
+ cursor = resolver.query(Phone.CONTENT_URI,
+ new String[] { Phone._ID },
+ Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
+ new String[] { String.valueOf(ci.person_id), normalizedPhoneNumber},
+ null);
+ } else {
+ final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
+ cursor = resolver.query(Phone.CONTENT_URI,
+ new String[] { Phone._ID },
+ Phone.CONTACT_ID + " =? AND " + Phone.NUMBER + " =?",
+ new String[] { String.valueOf(ci.person_id), phoneNumber},
+ null);
+ }
+
+ if (cursor != null) {
+ try {
+ if (cursor.getCount() > 0 && cursor.moveToFirst()) {
+ final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
+ .appendPath(cursor.getString(0))
+ .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+ DataUsageFeedback.USAGE_TYPE_CALL)
+ .build();
+ resolver.update(feedbackUri, new ContentValues(), null, null);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
}
Uri result = resolver.insert(CONTENT_URI, values);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index cb96bfd2..ad71061 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -174,6 +174,15 @@
*/
public static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
+ /**
+ * A boolean parameter for {@link Contacts#CONTENT_STREQUENT_URI} and
+ * {@link Contacts#CONTENT_STREQUENT_FILTER_URI}, which requires the ContactsProvider to
+ * return only phone-related results. For example, frequently contacted person list should
+ * include persons contacted via phone (not email, sms, etc.)
+ *
+ * @hide
+ */
+ public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only";
/**
* @hide
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 3436cd1..f45e78b 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1130,14 +1130,14 @@
public static final int BUTTON_PRIMARY = 1 << 0;
/**
- * Button constant: Secondary button (right mouse button, stylus barrel).
+ * Button constant: Secondary button (right mouse button, stylus first button).
*
* @see #getButtonState
*/
public static final int BUTTON_SECONDARY = 1 << 1;
/**
- * Button constant: Tertiary button (middle mouse button).
+ * Button constant: Tertiary button (middle mouse button, stylus second button).
*
* @see #getButtonState
*/
@@ -1165,13 +1165,6 @@
*/
public static final int BUTTON_FORWARD = 1 << 4;
- /**
- * Button constant: Eraser button pressed (stylus end).
- *
- * @see #getButtonState
- */
- public static final int BUTTON_ERASER = 1 << 5;
-
// NOTE: If you add a new axis here you must also add it to:
// native/include/android/input.h
@@ -1183,7 +1176,7 @@
"BUTTON_TERTIARY",
"BUTTON_BACK",
"BUTTON_FORWARD",
- "BUTTON_ERASER",
+ "0x00000020",
"0x00000040",
"0x00000080",
"0x00000100",
@@ -2176,7 +2169,6 @@
* @see #BUTTON_TERTIARY
* @see #BUTTON_FORWARD
* @see #BUTTON_BACK
- * @see #BUTTON_ERASER
*/
public final int getButtonState() {
return nativeGetButtonState(mNativePtr);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5743134..411b714 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3390,6 +3390,14 @@
}
/**
+ * Register a callback to be invoked when a hover event is sent to this view.
+ * @param l the hover listener to attach to this view
+ */
+ public void setOnHoverListener(OnHoverListener l) {
+ mOnHoverListener = l;
+ }
+
+ /**
* Register a drag event listener callback object for this View. The parameter is
* an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
* View, the system calls the
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 12687a1..7b65964 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,6 +41,7 @@
import android.util.Printer;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.TimeUtils;
import java.io.BufferedReader;
import java.io.File;
@@ -4870,8 +4871,8 @@
return 0;
}
- void readHistory(Parcel in) {
- mHistoryBaseTime = in.readLong();
+ void readHistory(Parcel in, boolean andOldHistory) {
+ final long historyBaseTime = in.readLong();
mHistoryBuffer.setDataSize(0);
mHistoryBuffer.setDataPosition(0);
@@ -4889,15 +4890,35 @@
in.setDataPosition(curPos + bufSize);
}
- long oldnow = SystemClock.elapsedRealtime() - (5*60*1000);
- if (oldnow > 0) {
- // If the system process has restarted, but not the entire
- // system, then the mHistoryBaseTime already accounts for
- // much of the elapsed time. We thus want to adjust it back,
- // to avoid large gaps in the data. We determine we are
- // in this case by arbitrarily saying it is so if at this
- // point in boot the elapsed time is already more than 5 minutes.
- mHistoryBaseTime -= oldnow;
+ if (andOldHistory) {
+ readOldHistory(in);
+ }
+
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** OLD mHistoryBaseTime: ");
+ TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ mHistoryBaseTime = historyBaseTime;
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** NEW mHistoryBaseTime: ");
+ TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ Slog.i(TAG, sb.toString());
+ }
+
+ // We are just arbitrarily going to insert 1 minute from the sample of
+ // the last run until samples in this run.
+ if (mHistoryBaseTime > 0) {
+ long oldnow = SystemClock.elapsedRealtime();
+ mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000;
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** ADJUSTED mHistoryBaseTime: ");
+ TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ Slog.i(TAG, sb.toString());
+ }
}
}
@@ -4910,12 +4931,24 @@
}
}
- void writeHistory(Parcel out) {
- out.writeLong(mLastHistoryTime);
+ void writeHistory(Parcel out, boolean andOldHistory) {
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** WRITING mHistoryBaseTime: ");
+ TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ sb.append(" mLastHistoryTime: ");
+ TimeUtils.formatDuration(mLastHistoryTime, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ out.writeLong(mHistoryBaseTime + mLastHistoryTime);
out.writeInt(mHistoryBuffer.dataSize());
if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
+ mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
+
+ if (andOldHistory) {
+ writeOldHistory(out);
+ }
}
void writeOldHistory(Parcel out) {
@@ -4935,8 +4968,7 @@
return;
}
- readHistory(in);
- readOldHistory(in);
+ readHistory(in, true);
mStartCount = in.readInt();
mBatteryUptime = in.readLong();
@@ -5136,8 +5168,7 @@
out.writeInt(VERSION);
- writeHistory(out);
- writeOldHistory(out);
+ writeHistory(out, true);
out.writeInt(mStartCount);
out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED));
@@ -5340,7 +5371,7 @@
throw new ParcelFormatException("Bad magic number");
}
- readHistory(in);
+ readHistory(in, false);
mStartCount = in.readInt();
mBatteryUptime = in.readLong();
@@ -5461,7 +5492,7 @@
out.writeInt(MAGIC);
- writeHistory(out);
+ writeHistory(out, false);
out.writeInt(mStartCount);
out.writeLong(mBatteryUptime);
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 3e7b976..5b35104 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -224,8 +224,8 @@
/**
* Animation used to attract user's attention to the target button.
- * Assumes mChevronDrawables is an a list with an even number of chevrons filled with left
- * followed by right chevrons.
+ * Assumes mChevronDrawables is an a list with an even number of chevrons filled with
+ * mFeedbackCount items in the order: left, right, top, bottom.
*/
private void startChevronAnimation() {
final float r = mHandleDrawable.getWidth() / 2;
@@ -442,6 +442,7 @@
mHandleDrawable.setX(mWaveCenterX);
mHandleDrawable.setY(mWaveCenterY);
mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+ Tweener.reset();
}
@Override
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
index 0cff00a..bc8a62f 100644
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
@@ -18,25 +18,42 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map.Entry;
import android.animation.Animator.AnimatorListener;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.util.Log;
class Tweener {
private static final String TAG = "Tweener";
+ private static final boolean DEBUG = false;
- private Object object;
ObjectAnimator animator;
private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>();
- public Tweener(Object obj, ObjectAnimator anim) {
- object = obj;
+ public Tweener(ObjectAnimator anim) {
animator = anim;
}
+ private static void remove(Animator animator) {
+ Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator();
+ while (iter.hasNext()) {
+ Entry<Object, Tweener> entry = iter.next();
+ if (entry.getValue().animator == animator) {
+ if (DEBUG) Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey())
+ + " sTweens.size() = " + sTweens.size());
+ iter.remove();
+ break; // an animator can only be attached to one object
+ }
+ }
+ }
+
public static Tweener to(Object object, long duration, Object... vars) {
long delay = 0;
AnimatorUpdateListener updateListener = null;
@@ -77,32 +94,35 @@
// Re-use existing tween, if present
Tweener tween = sTweens.get(object);
+ ObjectAnimator anim = null;
if (tween == null) {
- ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(object,
+ anim = ObjectAnimator.ofPropertyValuesHolder(object,
props.toArray(new PropertyValuesHolder[props.size()]));
- tween = new Tweener(object, anim);
+ tween = new Tweener(anim);
sTweens.put(object, tween);
+ if (DEBUG) Log.v(TAG, "Added new Tweener " + tween);
} else {
- tween.animator.cancel();
- replace(props, object);
+ anim = sTweens.get(object).animator;
+ replace(props, object); // Cancel all animators for given object
}
if (interpolator != null) {
- tween.animator.setInterpolator(interpolator);
+ anim.setInterpolator(interpolator);
}
// Update animation with properties discovered in loop above
- tween.animator.setStartDelay(delay);
- tween.animator.setDuration(duration);
+ anim.setStartDelay(delay);
+ anim.setDuration(duration);
if (updateListener != null) {
- tween.animator.removeAllUpdateListeners(); // There should be only one
- tween.animator.addUpdateListener(updateListener);
+ anim.removeAllUpdateListeners(); // There should be only one
+ anim.addUpdateListener(updateListener);
}
if (listener != null) {
- tween.animator.removeAllListeners(); // There should be only one.
- tween.animator.addListener(listener);
+ anim.removeAllListeners(); // There should be only one.
+ anim.addListener(listener);
}
- tween.animator.start();
+ anim.addListener(mCleanupListener);
+ anim.start();
return tween;
}
@@ -114,18 +134,40 @@
return Tweener.to(object, duration, vars);
}
- static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
+ // Listener to watch for completed animations and remove them.
+ private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() {
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ remove(animation);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ remove(animation);
+ }
+ };
+
+ public static void reset() {
+ if (DEBUG) {
+ Log.v(TAG, "Reset()");
+ if (sTweens.size() > 0) {
+ Log.v(TAG, "Cleaning up " + sTweens.size() + " animations");
+ }
+ }
+ sTweens.clear();
+ }
+
+ private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
for (final Object killobject : args) {
Tweener tween = sTweens.get(killobject);
if (tween != null) {
- if (killobject == tween.object) {
- tween.animator.cancel();
- if (props != null) {
- tween.animator.setValues(
- props.toArray(new PropertyValuesHolder[props.size()]));
- } else {
- sTweens.remove(tween);
- }
+ tween.animator.cancel();
+ if (props != null) {
+ tween.animator.setValues(
+ props.toArray(new PropertyValuesHolder[props.size()]));
+ } else {
+ sTweens.remove(tween);
}
}
}
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index dd8b378..2de0932 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -233,12 +233,6 @@
return surfaceTexture->getTimestamp();
}
-static jint SurfaceTexture_getQueuedCount(JNIEnv* env, jobject thiz)
-{
- sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
- return surfaceTexture->getQueuedCount();
-}
-
// ----------------------------------------------------------------------------
static JNINativeMethod gSurfaceTextureMethods[] = {
@@ -249,7 +243,6 @@
{"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage },
{"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
{"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp },
- {"nativeGetQueuedCount", "()I", (void*)SurfaceTexture_getQueuedCount }
};
int register_android_graphics_SurfaceTexture(JNIEnv* env)
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
index e21a87c..0f4bfe6 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
index 3283f99..995705d 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
index c10344f..754d7bc 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
index 08c6cfe..0187a02 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
new file mode 100644
index 0000000..544924e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
new file mode 100644
index 0000000..2d28009
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index d6a0cdd..13bbac6 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -23,9 +23,6 @@
<!-- see comment in values/config.xml -->
<integer name="config_longPressOnPowerBehavior">2</integer>
- <!-- Show sliding tab before lockscreen -->
- <bool name="config_enableSlidingTabFirst">false</bool>
-
<!-- Enable lockscreen rotation -->
<bool name="config_enableLockScreenRotation">true</bool>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0ad3184..827153e 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3,16 +3,16 @@
/*
** Copyright 2009, 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
+** 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
+** 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
+** 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.
*/
-->
@@ -54,25 +54,25 @@
connected. If you use the ims apn DCT will block
any other apn from connecting until ims apn is connected-->
<bool name="ImsConnectedDefaultValue">false</bool>
-
+
<!-- Flag indicating whether the surface flinger is inefficient
at performing a blur. Used by parts of the UI to turn off
the blur effect where it isn't worth the performance hit. -->
<bool name="config_sf_slowBlur">false</bool>
-
+
<!-- The duration (in milliseconds) of a short animation. -->
<integer name="config_shortAnimTime">200</integer>
-
+
<!-- The duration (in milliseconds) of a medium-length animation. -->
<integer name="config_mediumAnimTime">400</integer>
-
+
<!-- The duration (in milliseconds) of a long animation. -->
<integer name="config_longAnimTime">500</integer>
<!-- The duration (in milliseconds) of the activity open/close and fragment open/close animations. -->
<integer name="config_activityShortDur">150</integer>
<integer name="config_activityDefaultDur">220</integer>
-
+
<!-- Duration for the dim animation behind a dialog. This may be either
a percentage, which is relative to the duration of the enter/open
animation of the window being shown that is dimming behind, or it may
@@ -83,11 +83,11 @@
maximum (let them grow as large as the screen). Actual values are
specified for -large and -xlarge configurations. -->
<dimen name="config_prefDialogWidth">320dp</dimen>
-
+
<!-- Whether dialogs should close automatically when the user touches outside
of them. This should not normally be modified. -->
<bool name="config_closeDialogWhenTouchOutside">false</bool>
-
+
<!-- The duration (in milliseconds) that the radio will scan for a signal
when there's no network connection. If the scan doesn't timeout, use zero -->
<integer name="config_radioScanningTimeout">0</integer>
@@ -202,7 +202,7 @@
the slider is open. This can be set or unset depending how easily
the slider can be opened (for example, in a pocket or purse). -->
<bool name="config_bypass_keyguard_if_slider_open">true</bool>
-
+
<!-- Flag indicating whether the we should enable the automatic brightness in Settings.
Software implementation will be used if config_hardware_auto_brightness_available is not set -->
<bool name="config_automatic_brightness_available">false</bool>
@@ -212,10 +212,10 @@
<!-- If this is true, the screen will come on when you unplug usb/power/whatever. -->
<bool name="config_unplugTurnsOnScreen">false</bool>
-
+
<!-- If this is true, the screen will fade off. -->
<bool name="config_animateScreenLights">true</bool>
-
+
<!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
<!-- If true, the screen can be rotated via the accelerometer in all 4
@@ -300,7 +300,7 @@
<item>20</item>
<item>21</item>
</integer-array>
-
+
<!-- Vibrator pattern for feedback about touching a virtual key -->
<integer-array name="config_virtualKeyVibePattern">
<item>0</item>
@@ -380,8 +380,8 @@
<!-- Allow the menu hard key to be disabled in LockScreen on some devices -->
<bool name="config_disableMenuKeyInLockScreen">false</bool>
- <!-- Show sliding tab before lockscreen -->
- <bool name="config_enableSlidingTabFirst">true</bool>
+ <!-- Don't show lock screen before unlock screen (PIN/pattern/password) -->
+ <bool name="config_enableLockBeforeUnlockScreen">false</bool>
<!-- Diable lockscreen rotation by default -->
<bool name="config_enableLockScreenRotation">false</bool>
@@ -460,7 +460,7 @@
This feature should be disabled for most devices. -->
<integer name="config_virtualKeyQuietTimeMillis">0</integer>
- <!-- Component name of the default wallpaper. This will be ImageWallpaper if not
+ <!-- Component name of the default wallpaper. This will be ImageWallpaper if not
specified -->
<string name="default_wallpaper_component">@null</string>
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index adb6eac..90a7ac2 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -144,10 +144,6 @@
*/
public void updateTexImage() {
nativeUpdateTexImage();
- if (nativeGetQueuedCount() > 0) {
- Message m = mEventHandler.obtainMessage();
- mEventHandler.sendMessage(m);
- }
}
/**
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index e558dfd..c82fb9b 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -46,11 +46,14 @@
enum { NUM_BUFFER_SLOTS = 32 };
struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called from queueBuffer() is the FIFO is
- // empty. You can use SurfaceTexture::getQueuedCount() to
- // figure out if there are more frames waiting.
- // This is called without any lock held can be called concurrently by
- // multiple threads.
+ // onFrameAvailable() is called from queueBuffer() each time an
+ // additional frame becomes available for consumption. This means that
+ // frames that are queued while in asynchronous mode only trigger the
+ // callback if no previous frames are pending. Frames queued while in
+ // synchronous mode always trigger the callback.
+ //
+ // This is called without any lock held and can be called concurrently
+ // by multiple threads.
virtual void onFrameAvailable() = 0;
};
@@ -101,11 +104,6 @@
// target texture belongs is bound to the calling thread.
status_t updateTexImage();
- // getqueuedCount returns the number of queued frames waiting in the
- // FIFO. In asynchronous mode, this always returns 0 or 1 since
- // frames are not accumulating in the FIFO.
- size_t getQueuedCount() const;
-
// setBufferCountServer set the buffer count. If the client has requested
// a buffer count using setBufferCount, the server-buffer count will
// take effect once the client sets the count back to zero.
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 37e6d11..0925001 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -417,17 +417,22 @@
return -EINVAL;
}
- if (mQueue.empty()) {
- listener = mFrameAvailableListener;
- }
-
if (mSynchronousMode) {
- // in synchronous mode we queue all buffers in a FIFO
+ // In synchronous mode we queue all buffers in a FIFO.
mQueue.push_back(buf);
+
+ // Synchronous mode always signals that an additional frame should
+ // be consumed.
+ listener = mFrameAvailableListener;
} else {
- // in asynchronous mode we only keep the most recent buffer
+ // In asynchronous mode we only keep the most recent buffer.
if (mQueue.empty()) {
mQueue.push_back(buf);
+
+ // Asynchronous mode only signals that a frame should be
+ // consumed if no previous frame was pending. If a frame were
+ // pending then the consumer would have already been notified.
+ listener = mFrameAvailableListener;
} else {
Fifo::iterator front(mQueue.begin());
// buffer currently queued is freed
@@ -483,24 +488,14 @@
status_t SurfaceTexture::updateTexImage() {
LOGV("SurfaceTexture::updateTexImage");
-
Mutex::Autolock lock(mMutex);
- int buf = mCurrentTexture;
+ // In asynchronous mode the list is guaranteed to be one buffer
+ // deep, while in synchronous mode we use the oldest buffer.
if (!mQueue.empty()) {
- // in asynchronous mode the list is guaranteed to be one buffer deep,
- // while in synchronous mode we use the oldest buffer
Fifo::iterator front(mQueue.begin());
- buf = *front;
- mQueue.erase(front);
- if (mQueue.isEmpty()) {
- mDequeueCondition.signal();
- }
- }
+ int buf = *front;
- // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT,
- // so this check will fail until a buffer gets queued.
- if (mCurrentTexture != buf) {
// Update the GL texture object.
EGLImageKHR image = mSlots[buf].mEglImage;
if (image == EGL_NO_IMAGE_KHR) {
@@ -538,7 +533,7 @@
}
if (mCurrentTexture != INVALID_BUFFER_SLOT) {
- // the current buffer becomes FREE if it was still in the queued
+ // The current buffer becomes FREE if it was still in the queued
// state. If it has already been given to the client
// (synchronous mode), then it stays in DEQUEUED state.
if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
@@ -553,17 +548,17 @@
mCurrentTransform = mSlots[buf].mTransform;
mCurrentTimestamp = mSlots[buf].mTimestamp;
computeCurrentTransformMatrix();
+
+ // Now that we've passed the point at which failures can happen,
+ // it's safe to remove the buffer from the front of the queue.
+ mQueue.erase(front);
mDequeueCondition.signal();
} else {
// We always bind the texture even if we don't update its contents.
glBindTexture(mCurrentTextureTarget, mTexName);
}
- return OK;
-}
-size_t SurfaceTexture::getQueuedCount() const {
- Mutex::Autolock lock(mMutex);
- return mQueue.size();
+ return OK;
}
bool SurfaceTexture::isExternalFormat(uint32_t format)
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index f219639..dfa9211 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -419,6 +419,31 @@
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
}
+ class FrameWaiter : public SurfaceTexture::FrameAvailableListener {
+ public:
+ FrameWaiter():
+ mPendingFrames(0) {
+ }
+
+ void waitForFrame() {
+ Mutex::Autolock lock(mMutex);
+ while (mPendingFrames == 0) {
+ mCondition.wait(mMutex);
+ }
+ mPendingFrames--;
+ }
+
+ virtual void onFrameAvailable() {
+ Mutex::Autolock lock(mMutex);
+ mPendingFrames++;
+ mCondition.signal();
+ }
+
+ int mPendingFrames;
+ Mutex mMutex;
+ Condition mCondition;
+ };
+
sp<SurfaceTexture> mST;
sp<SurfaceTextureClient> mSTC;
sp<ANativeWindow> mANW;
@@ -648,6 +673,157 @@
}
}
+// This test is intended to catch synchronization bugs between the CPU-written
+// and GPU-read buffers.
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) {
+ enum { texWidth = 16 };
+ enum { texHeight = 16 };
+ enum { numFrames = 1024 };
+
+ ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
+ ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+ texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+ GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ struct TestPixel {
+ int x;
+ int y;
+ };
+ const TestPixel testPixels[] = {
+ { 4, 11 },
+ { 12, 14 },
+ { 7, 2 },
+ };
+ enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])};
+
+ class ProducerThread : public Thread {
+ public:
+ ProducerThread(const sp<ANativeWindow>& anw, const TestPixel* testPixels):
+ mANW(anw),
+ mTestPixels(testPixels) {
+ }
+
+ virtual ~ProducerThread() {
+ }
+
+ virtual bool threadLoop() {
+ for (int i = 0; i < numFrames; i++) {
+ ANativeWindowBuffer* anb;
+ if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+ return false;
+ }
+ if (anb == NULL) {
+ return false;
+ }
+
+ sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ if (mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())
+ != NO_ERROR) {
+ return false;
+ }
+
+ const int yuvTexOffsetY = 0;
+ int stride = buf->getStride();
+ int yuvTexStrideY = stride;
+ int yuvTexOffsetV = yuvTexStrideY * texHeight;
+ int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+ int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2;
+ int yuvTexStrideU = yuvTexStrideV;
+
+ uint8_t* img = NULL;
+ buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+ // Gray out all the test pixels first, so we're more likely to
+ // see a failure if GL is still texturing from the buffer we
+ // just dequeued.
+ for (int j = 0; j < numTestPixels; j++) {
+ int x = mTestPixels[j].x;
+ int y = mTestPixels[j].y;
+ uint8_t value = 128;
+ img[y*stride + x] = value;
+ }
+
+ // Fill the buffer with gray.
+ for (int y = 0; y < texHeight; y++) {
+ for (int x = 0; x < texWidth; x++) {
+ img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128;
+ img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128;
+ img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128;
+ }
+ }
+
+ // Set the test pixels to either white or black.
+ for (int j = 0; j < numTestPixels; j++) {
+ int x = mTestPixels[j].x;
+ int y = mTestPixels[j].y;
+ uint8_t value = 0;
+ if (j == (i % numTestPixels)) {
+ value = 255;
+ }
+ img[y*stride + x] = value;
+ }
+
+ buf->unlock();
+ if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())
+ != NO_ERROR) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ sp<ANativeWindow> mANW;
+ const TestPixel* mTestPixels;
+ };
+
+ sp<FrameWaiter> fw(new FrameWaiter);
+ mST->setFrameAvailableListener(fw);
+
+ sp<Thread> pt(new ProducerThread(mANW, testPixels));
+ pt->run();
+
+ glViewport(0, 0, texWidth, texHeight);
+
+ glClearColor(0.2, 0.2, 0.2, 0.2);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // We wait for the first two frames up front so that the producer will be
+ // likely to dequeue the buffer that's currently being textured from.
+ fw->waitForFrame();
+ fw->waitForFrame();
+
+ for (int i = 0; i < numFrames; i++) {
+ SCOPED_TRACE(String8::format("frame %d", i).string());
+
+ // We must wait for each frame to come in because if we ever do an
+ // updateTexImage call that doesn't consume a newly available buffer
+ // then the producer and consumer will get out of sync, which will cause
+ // a deadlock.
+ if (i > 1) {
+ fw->waitForFrame();
+ }
+ mST->updateTexImage();
+ drawTexture();
+
+ for (int j = 0; j < numTestPixels; j++) {
+ int x = testPixels[j].x;
+ int y = testPixels[j].y;
+ uint8_t value = 0;
+ if (j == (i % numTestPixels)) {
+ // We must y-invert the texture coords
+ EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255));
+ } else {
+ // We must y-invert the texture coords
+ EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255));
+ }
+ }
+ }
+
+ pt->requestExitAndWait();
+}
+
// XXX: This test is disabled because there are currently no drivers that can
// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) {
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index e43f6e5..8b1caeee 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -699,9 +699,10 @@
float* vertices = getFloats(verticesCount);
bool hasColors = getInt();
int* colors = hasColors ? getInts(colorsCount) : NULL;
+ SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
- renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint());
+ renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, paint);
}
break;
case DrawPatch: {
@@ -718,9 +719,15 @@
yDivs = getInts(yDivsCount);
colors = getUInts(numColors);
+ float left = getFloat();
+ float top = getFloat();
+ float right = getFloat();
+ float bottom = getFloat();
+ SkPaint* paint = getPaint();
+
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
- numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+ numColors, left, top, right, bottom, paint);
}
break;
case DrawColor: {
@@ -799,15 +806,17 @@
case DrawLines: {
int count = 0;
float* points = getFloats(count);
+ SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
- renderer.drawLines(points, count, getPaint());
+ renderer.drawLines(points, count, paint);
}
break;
case DrawPoints: {
int count = 0;
float* points = getFloats(count);
+ SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
- renderer.drawPoints(points, count, getPaint());
+ renderer.drawPoints(points, count, paint);
}
break;
case DrawText: {
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 26cac50..0d8ea28 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -404,7 +404,6 @@
AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
AMOTION_EVENT_BUTTON_BACK = 1 << 3,
AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
- AMOTION_EVENT_BUTTON_ERASER = 1 << 5,
};
/*
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index eea30407..b60bae7 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -682,8 +682,9 @@
final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
- boolean showSlidingTab = getResources().getBoolean(R.bool.config_enableSlidingTabFirst);
- if (isSecure() && (usingLockPattern || !showSlidingTab)) {
+ boolean showLockBeforeUnlock = getResources()
+ .getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
+ if (isSecure() && (usingLockPattern || !showLockBeforeUnlock)) {
return Mode.UnlockScreen;
} else {
return Mode.LockScreen;
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 3e4c666..5a25f8c 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -154,14 +154,15 @@
case BTN_LEFT:
return AMOTION_EVENT_BUTTON_PRIMARY;
case BTN_RIGHT:
+ case BTN_STYLUS:
return AMOTION_EVENT_BUTTON_SECONDARY;
case BTN_MIDDLE:
+ case BTN_STYLUS2:
return AMOTION_EVENT_BUTTON_TERTIARY;
case BTN_SIDE:
return AMOTION_EVENT_BUTTON_BACK;
- case BTN_EXTRA:
- return AMOTION_EVENT_BUTTON_FORWARD;
case BTN_FORWARD:
+ case BTN_EXTRA:
return AMOTION_EVENT_BUTTON_FORWARD;
case BTN_BACK:
return AMOTION_EVENT_BUTTON_BACK;
@@ -176,8 +177,7 @@
static bool isPointerDown(int32_t buttonState) {
return buttonState &
(AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
- | AMOTION_EVENT_BUTTON_TERTIARY
- | AMOTION_EVENT_BUTTON_ERASER);
+ | AMOTION_EVENT_BUTTON_TERTIARY);
}
static int32_t calculateEdgeFlagsUsingPointerBounds(
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index b4fdc9f..293702d 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -446,6 +446,15 @@
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
+ private void dumpHelp(PrintWriter pw) {
+ pw.println("Battery stats (batteryinfo) dump options:");
+ pw.println(" [--checkin] [--reset] [--write] [-h]");
+ pw.println(" --checkin: format output for a checkin report.");
+ pw.println(" --reset: reset the stats, clearing all current data.");
+ pw.println(" --write: force write current collected stats to disk.");
+ pw.println(" -h: print this help text.");
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
boolean isCheckin = false;
@@ -466,8 +475,12 @@
pw.println("Battery stats written.");
noOutput = true;
}
+ } else if ("-h".equals(arg)) {
+ dumpHelp(pw);
+ return;
} else {
pw.println("Unknown option: " + arg);
+ dumpHelp(pw);
}
}
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2bab6a8..35e29a6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -101,9 +101,8 @@
}
void Layer::onFrameQueued() {
- if (android_atomic_or(1, &mQueuedFrames) == 0) {
- mFlinger->signalEvent();
- }
+ android_atomic_inc(&mQueuedFrames);
+ mFlinger->signalEvent();
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
@@ -406,20 +405,18 @@
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- if (android_atomic_and(0, &mQueuedFrames)) {
+ if (mQueuedFrames > 0) {
+ // signal another event if we have more frames pending
+ if (android_atomic_dec(&mQueuedFrames) > 1) {
+ mFlinger->signalEvent();
+ }
+
if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
// something happened!
recomputeVisibleRegions = true;
return;
}
- // signal another event if we have more frames waiting
- if (mSurfaceTexture->getQueuedCount()) {
- if (android_atomic_or(1, &mQueuedFrames) == 0) {
- mFlinger->signalEvent();
- }
- }
-
mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
mSurfaceTexture->getTransformMatrix(mTextureMatrix);