summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/17.txt34
-rw-r--r--api/current.txt34
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java14
-rw-r--r--core/java/android/text/format/DateFormat.java97
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/webkit/AccessibilityInjector.java163
-rw-r--r--core/java/android/webkit/WebViewClassic.java3
-rw-r--r--core/java/android/widget/DigitalClock.java31
-rw-r--r--core/java/android/widget/TextClock.java482
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java5
-rw-r--r--core/res/AndroidManifest.xml13
-rw-r--r--core/res/res/layout-port/keyguard_host_view.xml10
-rw-r--r--core/res/res/layout-port/keyguard_widget_pager.xml2
-rw-r--r--core/res/res/layout/keyguard_pin_view.xml2
-rw-r--r--core/res/res/values-land/dimens.xml6
-rw-r--r--core/res/res/values-sw600dp/dimens.xml4
-rw-r--r--core/res/res/values-sw720dp/dimens.xml4
-rwxr-xr-xcore/res/res/values/attrs.xml20
-rwxr-xr-xcore/res/res/values/config.xml6
-rw-r--r--core/res/res/values/dimens.xml2
-rw-r--r--core/res/res/values/integers.xml4
-rw-r--r--core/res/res/values/public.xml3
-rwxr-xr-xcore/res/res/values/strings.xml35
-rw-r--r--core/res/res/values/symbols.xml5
-rw-r--r--core/tests/ConnectivityManagerTest/AndroidManifest.xml1
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java47
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java6
-rw-r--r--docs/html/guide/google/play/expansion-files.jd6
-rw-r--r--docs/html/guide/topics/ui/notifiers/notifications.jd128
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java5
-rw-r--r--libs/hwui/OpenGLRenderer.cpp2
-rw-r--r--location/java/android/location/Geofence.java4
-rw-r--r--location/java/android/location/LocationManager.java8
-rw-r--r--packages/SystemUI/res/values-da/strings.xml2
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml2
-rw-r--r--packages/SystemUI/res/values-es/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml2
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java15
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java93
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java47
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java1
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java48
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java8
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java44
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java44
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java4
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java152
-rwxr-xr-xservices/java/com/android/server/BluetoothManagerService.java62
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java11
53 files changed, 1475 insertions, 259 deletions
diff --git a/api/17.txt b/api/17.txt
index e26d8f0..fde6302 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -491,6 +491,8 @@ package android {
field public static final int foreground = 16843017; // 0x1010109
field public static final int foregroundGravity = 16843264; // 0x1010200
field public static final int format = 16843013; // 0x1010105
+ field public static final int format12Hour = 16843722; // 0x10103ca
+ field public static final int format24Hour = 16843723; // 0x10103cb
field public static final int fragment = 16843491; // 0x10102e3
field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8
@@ -1074,6 +1076,7 @@ package android {
field public static final int thumbTextPadding = 16843634; // 0x1010372
field public static final int thumbnail = 16843429; // 0x10102a5
field public static final int tileMode = 16843265; // 0x1010201
+ field public static final int timeZone = 16843724; // 0x10103cc
field public static final int tint = 16843041; // 0x1010121
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
@@ -22300,14 +22303,14 @@ package android.text.format {
public class DateFormat {
ctor public DateFormat();
- method public static final java.lang.CharSequence format(java.lang.CharSequence, long);
- method public static final java.lang.CharSequence format(java.lang.CharSequence, java.util.Date);
- method public static final java.lang.CharSequence format(java.lang.CharSequence, java.util.Calendar);
- method public static final java.text.DateFormat getDateFormat(android.content.Context);
- method public static final char[] getDateFormatOrder(android.content.Context);
- method public static final java.text.DateFormat getLongDateFormat(android.content.Context);
- method public static final java.text.DateFormat getMediumDateFormat(android.content.Context);
- method public static final java.text.DateFormat getTimeFormat(android.content.Context);
+ method public static java.lang.CharSequence format(java.lang.CharSequence, long);
+ method public static java.lang.CharSequence format(java.lang.CharSequence, java.util.Date);
+ method public static java.lang.CharSequence format(java.lang.CharSequence, java.util.Calendar);
+ method public static java.text.DateFormat getDateFormat(android.content.Context);
+ method public static char[] getDateFormatOrder(android.content.Context);
+ method public static java.text.DateFormat getLongDateFormat(android.content.Context);
+ method public static java.text.DateFormat getMediumDateFormat(android.content.Context);
+ method public static java.text.DateFormat getTimeFormat(android.content.Context);
method public static boolean is24HourFormat(android.content.Context);
field public static final char AM_PM = 97; // 0x0061 'a'
field public static final char CAPITAL_AM_PM = 65; // 0x0041 'A'
@@ -29518,6 +29521,21 @@ package android.widget {
field public int span;
}
+ public class TextClock extends android.widget.TextView {
+ ctor public TextClock(android.content.Context);
+ ctor public TextClock(android.content.Context, android.util.AttributeSet);
+ ctor public TextClock(android.content.Context, android.util.AttributeSet, int);
+ method public java.lang.CharSequence getFormat12Hour();
+ method public java.lang.CharSequence getFormat24Hour();
+ method public java.lang.String getTimeZone();
+ method public boolean is24HourModeEnabled();
+ method public void setFormat12Hour(java.lang.CharSequence);
+ method public void setFormat24Hour(java.lang.CharSequence);
+ method public void setTimeZone(java.lang.String);
+ field public static final java.lang.CharSequence DEFAULT_FORMAT_12_HOUR;
+ field public static final java.lang.CharSequence DEFAULT_FORMAT_24_HOUR;
+ }
+
public class TextSwitcher extends android.widget.ViewSwitcher {
ctor public TextSwitcher(android.content.Context);
ctor public TextSwitcher(android.content.Context, android.util.AttributeSet);
diff --git a/api/current.txt b/api/current.txt
index e26d8f0..fde6302 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -491,6 +491,8 @@ package android {
field public static final int foreground = 16843017; // 0x1010109
field public static final int foregroundGravity = 16843264; // 0x1010200
field public static final int format = 16843013; // 0x1010105
+ field public static final int format12Hour = 16843722; // 0x10103ca
+ field public static final int format24Hour = 16843723; // 0x10103cb
field public static final int fragment = 16843491; // 0x10102e3
field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8
@@ -1074,6 +1076,7 @@ package android {
field public static final int thumbTextPadding = 16843634; // 0x1010372
field public static final int thumbnail = 16843429; // 0x10102a5
field public static final int tileMode = 16843265; // 0x1010201
+ field public static final int timeZone = 16843724; // 0x10103cc
field public static final int tint = 16843041; // 0x1010121
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
@@ -22300,14 +22303,14 @@ package android.text.format {
public class DateFormat {
ctor public DateFormat();
- method public static final java.lang.CharSequence format(java.lang.CharSequence, long);
- method public static final java.lang.CharSequence format(java.lang.CharSequence, java.util.Date);
- method public static final java.lang.CharSequence format(java.lang.CharSequence, java.util.Calendar);
- method public static final java.text.DateFormat getDateFormat(android.content.Context);
- method public static final char[] getDateFormatOrder(android.content.Context);
- method public static final java.text.DateFormat getLongDateFormat(android.content.Context);
- method public static final java.text.DateFormat getMediumDateFormat(android.content.Context);
- method public static final java.text.DateFormat getTimeFormat(android.content.Context);
+ method public static java.lang.CharSequence format(java.lang.CharSequence, long);
+ method public static java.lang.CharSequence format(java.lang.CharSequence, java.util.Date);
+ method public static java.lang.CharSequence format(java.lang.CharSequence, java.util.Calendar);
+ method public static java.text.DateFormat getDateFormat(android.content.Context);
+ method public static char[] getDateFormatOrder(android.content.Context);
+ method public static java.text.DateFormat getLongDateFormat(android.content.Context);
+ method public static java.text.DateFormat getMediumDateFormat(android.content.Context);
+ method public static java.text.DateFormat getTimeFormat(android.content.Context);
method public static boolean is24HourFormat(android.content.Context);
field public static final char AM_PM = 97; // 0x0061 'a'
field public static final char CAPITAL_AM_PM = 65; // 0x0041 'A'
@@ -29518,6 +29521,21 @@ package android.widget {
field public int span;
}
+ public class TextClock extends android.widget.TextView {
+ ctor public TextClock(android.content.Context);
+ ctor public TextClock(android.content.Context, android.util.AttributeSet);
+ ctor public TextClock(android.content.Context, android.util.AttributeSet, int);
+ method public java.lang.CharSequence getFormat12Hour();
+ method public java.lang.CharSequence getFormat24Hour();
+ method public java.lang.String getTimeZone();
+ method public boolean is24HourModeEnabled();
+ method public void setFormat12Hour(java.lang.CharSequence);
+ method public void setFormat24Hour(java.lang.CharSequence);
+ method public void setTimeZone(java.lang.String);
+ field public static final java.lang.CharSequence DEFAULT_FORMAT_12_HOUR;
+ field public static final java.lang.CharSequence DEFAULT_FORMAT_24_HOUR;
+ }
+
public class TextSwitcher extends android.widget.ViewSwitcher {
ctor public TextSwitcher(android.content.Context);
ctor public TextSwitcher(android.content.Context, android.util.AttributeSet);
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 2af65b9..3dd640c 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -80,6 +80,13 @@ public class AppWidgetManager {
public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
/**
+ * Similar to ACTION_APPWIDGET_PICK, but used from keyguard
+ * @hide
+ */
+ public static final String
+ ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK";
+
+ /**
* Send this from your {@link AppWidgetHost} activity when you want to bind an AppWidget to
* display and bindAppWidgetIdIfAllowed returns false.
* <p>
@@ -224,13 +231,6 @@ public class AppWidgetManager {
public static final String EXTRA_CATEGORY_FILTER = "categoryFilter";
/**
- * An intent extra to pass to the AppWidget picker which allows the picker to filter
- * the list based on the {@link AppWidgetProviderInfo#widgetFeatures}.
- * @hide
- */
- public static final String EXTRA_FEATURES_FILTER = "featuresFilter";
-
- /**
* An intent extra to pass to the AppWidget picker to specify whether or not to sort
* the list of caller-specified extra AppWidgets along with the rest of the AppWidgets
* @hide
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index c36273e..3c984b5 100644
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -249,12 +249,13 @@ public class DateFormat {
synchronized (sLocaleLock) {
sIs24HourLocale = locale;
- sIs24Hour = !value.equals("12");
+ sIs24Hour = value.equals("24");
}
+
+ return sIs24Hour;
}
- boolean b24 = !(value == null || value.equals("12"));
- return b24;
+ return value.equals("24");
}
/**
@@ -263,7 +264,7 @@ public class DateFormat {
* @param context the application context
* @return the {@link java.text.DateFormat} object that properly formats the time.
*/
- public static final java.text.DateFormat getTimeFormat(Context context) {
+ public static java.text.DateFormat getTimeFormat(Context context) {
boolean b24 = is24HourFormat(context);
int res;
@@ -283,7 +284,7 @@ public class DateFormat {
* @param context the application context
* @return the {@link java.text.DateFormat} object that properly formats the date.
*/
- public static final java.text.DateFormat getDateFormat(Context context) {
+ public static java.text.DateFormat getDateFormat(Context context) {
String value = Settings.System.getString(context.getContentResolver(),
Settings.System.DATE_FORMAT);
@@ -353,7 +354,7 @@ public class DateFormat {
* @param context the application context
* @return the {@link java.text.DateFormat} object that formats the date in long form.
*/
- public static final java.text.DateFormat getLongDateFormat(Context context) {
+ public static java.text.DateFormat getLongDateFormat(Context context) {
return java.text.DateFormat.getDateInstance(java.text.DateFormat.LONG);
}
@@ -363,7 +364,7 @@ public class DateFormat {
* @param context the application context
* @return the {@link java.text.DateFormat} object that formats the date in long form.
*/
- public static final java.text.DateFormat getMediumDateFormat(Context context) {
+ public static java.text.DateFormat getMediumDateFormat(Context context) {
return java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM);
}
@@ -376,7 +377,7 @@ public class DateFormat {
* not just the day, month, and year, and not necessarily in the same
* order returned here.
*/
- public static final char[] getDateFormatOrder(Context context) {
+ public static char[] getDateFormatOrder(Context context) {
char[] order = new char[] {DATE, MONTH, YEAR};
String value = getDateFormatString(context);
int index = 0;
@@ -420,7 +421,7 @@ public class DateFormat {
* @param inTimeInMillis in milliseconds since Jan 1, 1970 GMT
* @return a {@link CharSequence} containing the requested text
*/
- public static final CharSequence format(CharSequence inFormat, long inTimeInMillis) {
+ public static CharSequence format(CharSequence inFormat, long inTimeInMillis) {
return format(inFormat, new Date(inTimeInMillis));
}
@@ -431,7 +432,7 @@ public class DateFormat {
* @param inDate the date to format
* @return a {@link CharSequence} containing the requested text
*/
- public static final CharSequence format(CharSequence inFormat, Date inDate) {
+ public static CharSequence format(CharSequence inFormat, Date inDate) {
Calendar c = new GregorianCalendar();
c.setTime(inDate);
@@ -440,13 +441,75 @@ public class DateFormat {
}
/**
+ * Indicates whether the specified format string contains seconds.
+ *
+ * Always returns false if the input format is null.
+ *
+ * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
+ *
+ * @return true if the format string contains {@link #SECONDS}, false otherwise
+ *
+ * @hide
+ */
+ public static boolean hasSeconds(CharSequence inFormat) {
+ if (inFormat == null) return false;
+
+ final int length = inFormat.length();
+
+ int c;
+ int count;
+
+ for (int i = 0; i < length; i += count) {
+ count = 1;
+ c = inFormat.charAt(i);
+
+ if (c == QUOTE) {
+ count = skipQuotedText(inFormat, i, length);
+ } else if (c == SECONDS) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static int skipQuotedText(CharSequence s, int i, int len) {
+ if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
+ return 2;
+ }
+
+ int count = 1;
+ // skip leading quote
+ i++;
+
+ while (i < len) {
+ char c = s.charAt(i);
+
+ if (c == QUOTE) {
+ count++;
+ // QUOTEQUOTE -> QUOTE
+ if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
+ i++;
+ } else {
+ break;
+ }
+ } else {
+ i++;
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ /**
* Given a format string and a {@link java.util.Calendar} object, returns a CharSequence
* containing the requested date.
* @param inFormat the format string, as described in {@link android.text.format.DateFormat}
* @param inDate the date to format
* @return a {@link CharSequence} containing the requested text
*/
- public static final CharSequence format(CharSequence inFormat, Calendar inDate) {
+ public static CharSequence format(CharSequence inFormat, Calendar inDate) {
SpannableStringBuilder s = new SpannableStringBuilder(inFormat);
int c;
int count;
@@ -545,7 +608,7 @@ public class DateFormat {
return s.toString();
}
- private static final String getMonthString(Calendar inDate, int count, int kind) {
+ private static String getMonthString(Calendar inDate, int count, int kind) {
boolean standalone = (kind == STANDALONE_MONTH);
int month = inDate.get(Calendar.MONTH);
@@ -563,7 +626,7 @@ public class DateFormat {
}
}
- private static final String getTimeZoneString(Calendar inDate, int count) {
+ private static String getTimeZoneString(Calendar inDate, int count) {
TimeZone tz = inDate.getTimeZone();
if (count < 2) { // FIXME: shouldn't this be <= 2 ?
@@ -576,7 +639,7 @@ public class DateFormat {
}
}
- private static final String formatZoneOffset(int offset, int count) {
+ private static String formatZoneOffset(int offset, int count) {
offset /= 1000; // milliseconds to seconds
StringBuilder tb = new StringBuilder();
@@ -595,13 +658,13 @@ public class DateFormat {
return tb.toString();
}
- private static final String getYearString(Calendar inDate, int count) {
+ private static String getYearString(Calendar inDate, int count) {
int year = inDate.get(Calendar.YEAR);
return (count <= 2) ? zeroPad(year % 100, 2)
: String.format(Locale.getDefault(), "%d", year);
}
- private static final int appendQuotedText(SpannableStringBuilder s, int i, int len) {
+ private static int appendQuotedText(SpannableStringBuilder s, int i, int len) {
if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
s.delete(i, i + 1);
return 1;
@@ -638,7 +701,7 @@ public class DateFormat {
return count;
}
- private static final String zeroPad(int inValue, int inMinDigits) {
+ private static String zeroPad(int inValue, int inMinDigits) {
return String.format(Locale.getDefault(), "%0" + inMinDigits + "d", inValue);
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9d0d4f0..d5e1ed3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17697,7 +17697,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
boolean mScalingRequired;
/**
- * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
+ * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
*/
boolean mTurnOffWindowResizeAnim;
diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index 95a0416..008a615 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -18,6 +18,7 @@ package android.webkit;
import android.content.Context;
import android.os.Bundle;
+import android.os.Handler;
import android.os.SystemClock;
import android.provider.Settings;
import android.speech.tts.TextToSpeech;
@@ -159,7 +160,7 @@ class AccessibilityInjector {
* <p>
* This should only be called before a page loads.
*/
- private void addAccessibilityApisIfNecessary() {
+ public void addAccessibilityApisIfNecessary() {
if (!isAccessibilityEnabled() || !isJavaScriptEnabled()) {
return;
}
@@ -333,8 +334,9 @@ class AccessibilityInjector {
*/
public void onPageStarted(String url) {
mAccessibilityScriptInjected = false;
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "[" + mWebView.hashCode() + "] Started loading new page");
+ }
addAccessibilityApisIfNecessary();
}
@@ -348,30 +350,57 @@ class AccessibilityInjector {
*/
public void onPageFinished(String url) {
if (!isAccessibilityEnabled()) {
- mAccessibilityScriptInjected = false;
toggleFallbackAccessibilityInjector(false);
return;
}
- if (!shouldInjectJavaScript(url)) {
- mAccessibilityScriptInjected = false;
- toggleFallbackAccessibilityInjector(true);
- if (DEBUG)
- Log.d(TAG, "[" + mWebView.hashCode() + "] Using fallback accessibility support");
- return;
+ toggleFallbackAccessibilityInjector(true);
+
+ if (shouldInjectJavaScript(url)) {
+ // If we're supposed to use the JS screen reader, request a
+ // callback to confirm that CallbackHandler is working.
+ if (DEBUG) {
+ Log.d(TAG, "[" + mWebView.hashCode() + "] Request callback ");
+ }
+
+ mCallback.requestCallback(mWebView, mInjectScriptRunnable);
+ }
+ }
+
+ /**
+ * Runnable used to inject the JavaScript-based screen reader if the
+ * {@link CallbackHandler} API was successfully exposed to JavaScript.
+ */
+ private Runnable mInjectScriptRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG) {
+ Log.d(TAG, "[" + mWebView.hashCode() + "] Received callback");
+ }
+
+ injectJavaScript();
}
+ };
+ /**
+ * Called by {@link #mInjectScriptRunnable} to inject the JavaScript-based
+ * screen reader after confirming that the {@link CallbackHandler} API is
+ * functional.
+ */
+ private void injectJavaScript() {
toggleFallbackAccessibilityInjector(false);
if (!mAccessibilityScriptInjected) {
mAccessibilityScriptInjected = true;
final String injectionUrl = getScreenReaderInjectionUrl();
mWebView.loadUrl(injectionUrl);
- if (DEBUG)
+ if (DEBUG) {
Log.d(TAG, "[" + mWebView.hashCode() + "] Loading screen reader into WebView");
+ }
} else {
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "[" + mWebView.hashCode() + "] Attempted to inject screen reader twice");
+ }
}
}
@@ -447,12 +476,10 @@ class AccessibilityInjector {
* been done.
*/
private void addTtsApis() {
- if (mTextToSpeech != null) {
- return;
+ if (mTextToSpeech == null) {
+ mTextToSpeech = new TextToSpeechWrapper(mContext);
}
- if (DEBUG)
- Log.d(TAG, "[" + mWebView.hashCode() + "] Adding TTS APIs into WebView");
- mTextToSpeech = new TextToSpeechWrapper(mContext);
+
mWebView.addJavascriptInterface(mTextToSpeech, ALIAS_TTS_JS_INTERFACE);
}
@@ -461,34 +488,29 @@ class AccessibilityInjector {
* already been done.
*/
private void removeTtsApis() {
- if (mTextToSpeech == null) {
- return;
+ if (mTextToSpeech != null) {
+ mTextToSpeech.stop();
+ mTextToSpeech.shutdown();
+ mTextToSpeech = null;
}
- if (DEBUG)
- Log.d(TAG, "[" + mWebView.hashCode() + "] Removing TTS APIs from WebView");
mWebView.removeJavascriptInterface(ALIAS_TTS_JS_INTERFACE);
- mTextToSpeech.stop();
- mTextToSpeech.shutdown();
- mTextToSpeech = null;
}
private void addCallbackApis() {
- if (mCallback != null) {
- return;
+ if (mCallback == null) {
+ mCallback = new CallbackHandler(ALIAS_TRAVERSAL_JS_INTERFACE);
}
- mCallback = new CallbackHandler(ALIAS_TRAVERSAL_JS_INTERFACE);
mWebView.addJavascriptInterface(mCallback, ALIAS_TRAVERSAL_JS_INTERFACE);
}
private void removeCallbackApis() {
- if (mCallback == null) {
- return;
+ if (mCallback != null) {
+ mCallback = null;
}
mWebView.removeJavascriptInterface(ALIAS_TRAVERSAL_JS_INTERFACE);
- mCallback = null;
}
/**
@@ -638,9 +660,10 @@ class AccessibilityInjector {
private volatile boolean mShutdown;
public TextToSpeechWrapper(Context context) {
- if (DEBUG)
+ if (DEBUG) {
Log.d(WRAP_TAG, "[" + hashCode() + "] Initializing text-to-speech on thread "
+ Thread.currentThread().getId() + "...");
+ }
final String pkgName = context.getPackageName();
@@ -672,12 +695,14 @@ class AccessibilityInjector {
public int speak(String text, int queueMode, HashMap<String, String> params) {
synchronized (mTextToSpeech) {
if (!mReady) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(WRAP_TAG, "[" + hashCode() + "] Attempted to speak before TTS init");
+ }
return TextToSpeech.ERROR;
} else {
- if (DEBUG)
+ if (DEBUG) {
Log.i(WRAP_TAG, "[" + hashCode() + "] Speak called from JS binder");
+ }
}
return mTextToSpeech.speak(text, queueMode, params);
@@ -689,12 +714,14 @@ class AccessibilityInjector {
public int stop() {
synchronized (mTextToSpeech) {
if (!mReady) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(WRAP_TAG, "[" + hashCode() + "] Attempted to stop before initialize");
+ }
return TextToSpeech.ERROR;
} else {
- if (DEBUG)
+ if (DEBUG) {
Log.i(WRAP_TAG, "[" + hashCode() + "] Stop called from JS binder");
+ }
}
return mTextToSpeech.stop();
@@ -705,12 +732,14 @@ class AccessibilityInjector {
protected void shutdown() {
synchronized (mTextToSpeech) {
if (!mReady) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(WRAP_TAG, "[" + hashCode() + "] Called shutdown before initialize");
+ }
} else {
- if (DEBUG)
+ if (DEBUG) {
Log.i(WRAP_TAG, "[" + hashCode() + "] Shutting down text-to-speech from "
+ "thread " + Thread.currentThread().getId() + "...");
+ }
}
mShutdown = true;
mReady = false;
@@ -723,14 +752,16 @@ class AccessibilityInjector {
public void onInit(int status) {
synchronized (mTextToSpeech) {
if (!mShutdown && (status == TextToSpeech.SUCCESS)) {
- if (DEBUG)
+ if (DEBUG) {
Log.d(WRAP_TAG, "[" + TextToSpeechWrapper.this.hashCode()
+ "] Initialized successfully");
+ }
mReady = true;
} else {
- if (DEBUG)
+ if (DEBUG) {
Log.w(WRAP_TAG, "[" + TextToSpeechWrapper.this.hashCode()
+ "] Failed to initialize");
+ }
mReady = false;
}
}
@@ -745,9 +776,10 @@ class AccessibilityInjector {
@Override
public void onError(String utteranceId) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(WRAP_TAG, "[" + TextToSpeechWrapper.this.hashCode()
+ "] Failed to speak utterance");
+ }
}
@Override
@@ -770,12 +802,16 @@ class AccessibilityInjector {
private final AtomicInteger mResultIdCounter = new AtomicInteger();
private final Object mResultLock = new Object();
private final String mInterfaceName;
+ private final Handler mMainHandler;
+
+ private Runnable mCallbackRunnable;
private boolean mResult = false;
private int mResultId = -1;
private CallbackHandler(String interfaceName) {
mInterfaceName = interfaceName;
+ mMainHandler = new Handler();
}
/**
@@ -826,25 +862,29 @@ class AccessibilityInjector {
private boolean waitForResultTimedLocked(int resultId) {
final long startTimeMillis = SystemClock.uptimeMillis();
- if (DEBUG)
+ if (DEBUG) {
Log.d(TAG, "Waiting for CVOX result with ID " + resultId + "...");
+ }
while (true) {
// Fail if we received a callback from the future.
if (mResultId > resultId) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "Aborted CVOX result");
+ }
return false;
}
final long elapsedTimeMillis = (SystemClock.uptimeMillis() - startTimeMillis);
// Succeed if we received the callback we were expecting.
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "Check " + mResultId + " versus expected " + resultId);
+ }
if (mResultId == resultId) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "Received CVOX result after " + elapsedTimeMillis + " ms");
+ }
return true;
}
@@ -852,18 +892,21 @@ class AccessibilityInjector {
// Fail if we've already exceeded the timeout.
if (waitTimeMillis <= 0) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "Timed out while waiting for CVOX result");
+ }
return false;
}
try {
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "Start waiting...");
+ }
mResultLock.wait(waitTimeMillis);
} catch (InterruptedException ie) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "Interrupted while waiting for CVOX result");
+ }
}
}
}
@@ -878,8 +921,9 @@ class AccessibilityInjector {
@JavascriptInterface
@SuppressWarnings("unused")
public void onResult(String id, String result) {
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "Saw CVOX result of '" + result + "' for ID " + id);
+ }
final int resultId;
try {
@@ -893,11 +937,34 @@ class AccessibilityInjector {
mResult = Boolean.parseBoolean(result);
mResultId = resultId;
} else {
- if (DEBUG)
+ if (DEBUG) {
Log.w(TAG, "Result with ID " + resultId + " was stale vesus " + mResultId);
+ }
}
mResultLock.notifyAll();
}
}
+
+ /**
+ * Requests a callback to ensure that the JavaScript interface for this
+ * object has been added successfully.
+ *
+ * @param webView The web view to request a callback from.
+ * @param callbackRunnable Runnable to execute if a callback is received.
+ */
+ public void requestCallback(WebView webView, Runnable callbackRunnable) {
+ mCallbackRunnable = callbackRunnable;
+
+ webView.loadUrl("javascript:(function() { " + mInterfaceName + ".callback(); })();");
+ }
+
+ @JavascriptInterface
+ @SuppressWarnings("unused")
+ public void callback() {
+ if (mCallbackRunnable != null) {
+ mMainHandler.post(mCallbackRunnable);
+ mCallbackRunnable = null;
+ }
+ }
}
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 0f8966e..ae56e6b 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -2500,6 +2500,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// Remove all pending messages because we are restoring previous
// state.
mWebViewCore.removeMessages();
+ if (isAccessibilityInjectionEnabled()) {
+ getAccessibilityInjector().addAccessibilityApisIfNecessary();
+ }
// Send a restore state message.
mWebViewCore.sendMessage(EventHub.RESTORE_STATE, index);
}
diff --git a/core/java/android/widget/DigitalClock.java b/core/java/android/widget/DigitalClock.java
index 3e9107f..c6b6dd6 100644
--- a/core/java/android/widget/DigitalClock.java
+++ b/core/java/android/widget/DigitalClock.java
@@ -17,7 +17,6 @@
package android.widget;
import android.content.Context;
-import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.SystemClock;
@@ -32,14 +31,12 @@ import java.util.Calendar;
/**
* Like AnalogClock, but digital. Shows seconds.
*
- * FIXME: implement separate views for hours/minutes/seconds, so
- * proportional fonts don't shake rendering
- *
- * @deprecated It is recommended you use a {@link TextView} and {@link DateFormat}
- * to implement the same behavior.
+ * @deprecated It is recommended you use {@link TextClock} instead.
*/
@Deprecated
public class DigitalClock extends TextView {
+ // FIXME: implement separate views for hours/minutes/seconds, so
+ // proportional fonts don't shake rendering
Calendar mCalendar;
private final static String m12 = "h:mm:ss aa";
@@ -86,16 +83,16 @@ public class DigitalClock extends TextView {
* requests a tick on the next hard-second boundary
*/
mTicker = new Runnable() {
- public void run() {
- if (mTickerStopped) return;
- mCalendar.setTimeInMillis(System.currentTimeMillis());
- setText(DateFormat.format(mFormat, mCalendar));
- invalidate();
- long now = SystemClock.uptimeMillis();
- long next = now + (1000 - now % 1000);
- mHandler.postAtTime(mTicker, next);
- }
- };
+ public void run() {
+ if (mTickerStopped) return;
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
+ setText(DateFormat.format(mFormat, mCalendar));
+ invalidate();
+ long now = SystemClock.uptimeMillis();
+ long next = now + (1000 - now % 1000);
+ mHandler.postAtTime(mTicker, next);
+ }
+ };
mTicker.run();
}
@@ -134,12 +131,14 @@ public class DigitalClock extends TextView {
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
+ //noinspection deprecation
event.setClassName(DigitalClock.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
+ //noinspection deprecation
info.setClassName(DigitalClock.class.getName());
}
}
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
new file mode 100644
index 0000000..4c46658
--- /dev/null
+++ b/core/java/android/widget/TextClock.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2012 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 android.widget;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.TypedArray;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+
+import com.android.internal.R;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import static android.view.ViewDebug.ExportedProperty;
+import static android.widget.RemoteViews.*;
+
+/**
+ * <p><code>TextClock</code> can display the current date and/or time as
+ * a formatted string.</p>
+ *
+ * <p>This view honors the 24-hour format system setting. As such, it is
+ * possible and recommended to provide two different formatting patterns:
+ * one to display the date/time in 24-hour mode and one to display the
+ * date/time in 12-hour mode.</p>
+ *
+ * <p>It is possible to determine whether the system is currently in
+ * 24-hour mode by calling {@link #is24HourModeEnabled()}.</p>
+ *
+ * <p>The rules used by this widget to decide how to format the date and
+ * time are the following:</p>
+ * <ul>
+ * <li>In 24-hour mode:
+ * <ul>
+ * <li>Use the value returned by {@link #getFormat24Hour()} when non-null</li>
+ * <li>Otherwise, use the value returned by {@link #getFormat12Hour()} when non-null</li>
+ * <li>Otherwise, use {@link #DEFAULT_FORMAT_24_HOUR}</li>
+ * </ul>
+ * </li>
+ * <li>In 12-hour mode:
+ * <ul>
+ * <li>Use the value returned by {@link #getFormat12Hour()} when non-null</li>
+ * <li>Otherwise, use the value returned by {@link #getFormat24Hour()} when non-null</li>
+ * <li>Otherwise, use {@link #DEFAULT_FORMAT_12_HOUR}</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * <p>The {@link CharSequence} instances used as formatting patterns when calling either
+ * {@link #setFormat24Hour(CharSequence)} or {@link #setFormat12Hour(CharSequence)} can
+ * contain styling information. To do so, use a {@link android.text.Spanned} object.</p>
+ *
+ * @attr ref android.R.styleable#TextClock_format12Hour
+ * @attr ref android.R.styleable#TextClock_format24Hour
+ * @attr ref android.R.styleable#TextClock_timeZone
+ */
+@RemoteView
+public class TextClock extends TextView {
+ /**
+ * The default formatting pattern in 12-hour mode. This pattenr is used
+ * if {@link #setFormat12Hour(CharSequence)} is called with a null pattern
+ * or if no pattern was specified when creating an instance of this class.
+ *
+ * This default pattern shows only the time, hours and minutes, and an am/pm
+ * indicator.
+ *
+ * @see #setFormat12Hour(CharSequence)
+ * @see #getFormat12Hour()
+ */
+ public static final CharSequence DEFAULT_FORMAT_12_HOUR = "h:mm aa";
+
+ /**
+ * The default formatting pattern in 24-hour mode. This pattenr is used
+ * if {@link #setFormat24Hour(CharSequence)} is called with a null pattern
+ * or if no pattern was specified when creating an instance of this class.
+ *
+ * This default pattern shows only the time, hours and minutes.
+ *
+ * @see #setFormat24Hour(CharSequence)
+ * @see #getFormat24Hour()
+ */
+ public static final CharSequence DEFAULT_FORMAT_24_HOUR = "k:mm";
+
+ private CharSequence mFormat12 = DEFAULT_FORMAT_12_HOUR;
+ private CharSequence mFormat24 = DEFAULT_FORMAT_24_HOUR;
+
+ @ExportedProperty
+ private CharSequence mFormat;
+ @ExportedProperty
+ private boolean mHasSeconds;
+
+ private boolean mAttached;
+
+ private Calendar mTime;
+ private String mTimeZone;
+
+ private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ chooseFormat();
+ onTimeChanged();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ chooseFormat();
+ onTimeChanged();
+ }
+ };
+
+ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mTimeZone == null) {
+ if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
+ final String timeZone = intent.getStringExtra("time-zone");
+ createTime(timeZone);
+ }
+ onTimeChanged();
+ }
+ }
+ };
+
+ private final Runnable mTicker = new Runnable() {
+ public void run() {
+ onTimeChanged();
+
+ long now = SystemClock.uptimeMillis();
+ long next = now + (1000 - now % 1000);
+
+ getHandler().postAtTime(mTicker, next);
+ }
+ };
+
+ /**
+ * Creates a new clock using the default patterns
+ * {@link #DEFAULT_FORMAT_24_HOUR} and {@link #DEFAULT_FORMAT_12_HOUR}
+ * respectively for the 24-hour and 12-hour modes.
+ *
+ * @param context The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public TextClock(Context context) {
+ super(context);
+ init();
+ }
+
+ /**
+ * Creates a new clock inflated from XML. This object's properties are
+ * intialized from the attributes specified in XML.
+ *
+ * This constructor uses a default style of 0, so the only attribute values
+ * applied are those in the Context's Theme and the given AttributeSet.
+ *
+ * @param context The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ * @param attrs The attributes of the XML tag that is inflating the view
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public TextClock(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ /**
+ * Creates a new clock inflated from XML. This object's properties are
+ * intialized from the attributes specified in XML.
+ *
+ * @param context The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ * @param attrs The attributes of the XML tag that is inflating the view
+ * @param defStyle The default style to apply to this view. If 0, no style
+ * will be applied (beyond what is included in the theme). This may
+ * either be an attribute resource, whose value will be retrieved
+ * from the current theme, or an explicit style resource
+ */
+ public TextClock(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextClock, defStyle, 0);
+ try {
+ CharSequence format;
+
+ format = a.getText(R.styleable.TextClock_format12Hour);
+ mFormat12 = format == null ? DEFAULT_FORMAT_12_HOUR : format;
+
+ format = a.getText(R.styleable.TextClock_format24Hour);
+ mFormat24 = format == null ? DEFAULT_FORMAT_24_HOUR : format;
+
+ mTimeZone = a.getString(R.styleable.TextClock_timeZone);
+ } finally {
+ a.recycle();
+ }
+
+ init();
+ }
+
+ private void init() {
+ createTime(mTimeZone);
+ // Wait until onAttachedToWindow() to handle the ticker
+ chooseFormat(false);
+ }
+
+ private void createTime(String timeZone) {
+ if (timeZone != null) {
+ mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
+ } else {
+ mTime = Calendar.getInstance();
+ }
+ }
+
+ /**
+ * Returns the formatting pattern used to display the date and/or time
+ * in 12-hour mode. The formatting pattern syntax is described in
+ * {@link DateFormat}.
+ *
+ * @return A {@link CharSequence} or null.
+ *
+ * @see #setFormat12Hour(CharSequence)
+ * @see #is24HourModeEnabled()
+ */
+ @ExportedProperty
+ public CharSequence getFormat12Hour() {
+ return mFormat12;
+ }
+
+ /**
+ * Specifies the formatting pattern used to display the date and/or time
+ * in 12-hour mode. The formatting pattern syntax is described in
+ * {@link DateFormat}.
+ *
+ * If this pattern is set to null, {@link #getFormat24Hour()} will be used
+ * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns
+ * are set to null, {@link #DEFAULT_FORMAT_24_HOUR} and
+ * {@link #DEFAULT_FORMAT_12_HOUR} will be used instead.
+ *
+ * @param format A date/time formatting pattern as described in {@link DateFormat}
+ *
+ * @see #getFormat12Hour()
+ * @see #is24HourModeEnabled()
+ * @see #DEFAULT_FORMAT_12_HOUR
+ * @see DateFormat
+ *
+ * @attr ref android.R.styleable#TextClock_format12Hour
+ */
+ public void setFormat12Hour(CharSequence format) {
+ mFormat12 = format;
+
+ chooseFormat();
+ onTimeChanged();
+ }
+
+ /**
+ * Returns the formatting pattern used to display the date and/or time
+ * in 24-hour mode. The formatting pattern syntax is described in
+ * {@link DateFormat}.
+ *
+ * @return A {@link CharSequence} or null.
+ *
+ * @see #setFormat24Hour(CharSequence)
+ * @see #is24HourModeEnabled()
+ */
+ @ExportedProperty
+ public CharSequence getFormat24Hour() {
+ return mFormat24;
+ }
+
+ /**
+ * Specifies the formatting pattern used to display the date and/or time
+ * in 24-hour mode. The formatting pattern syntax is described in
+ * {@link DateFormat}.
+ *
+ * If this pattern is set to null, {@link #getFormat12Hour()} will be used
+ * even in 24-hour mode. If both 24-hour and 12-hour formatting patterns
+ * are set to null, {@link #DEFAULT_FORMAT_24_HOUR} and
+ * {@link #DEFAULT_FORMAT_12_HOUR} will be used instead.
+ *
+ * @param format A date/time formatting pattern as described in {@link DateFormat}
+ *
+ * @see #getFormat24Hour()
+ * @see #is24HourModeEnabled()
+ * @see #DEFAULT_FORMAT_24_HOUR
+ * @see DateFormat
+ *
+ * @attr ref android.R.styleable#TextClock_format24Hour
+ */
+ public void setFormat24Hour(CharSequence format) {
+ mFormat24 = format;
+
+ chooseFormat();
+ onTimeChanged();
+ }
+
+ /**
+ * Indicates whether the system is currently using the 24-hour mode.
+ *
+ * When the system is in 24-hour mode, this view will use the pattern
+ * returned by {@link #getFormat24Hour()}. In 12-hour mode, the pattern
+ * returned by {@link #getFormat12Hour()} is used instead.
+ *
+ * If either one of the formats is null, the other format is used. If
+ * both formats are null, the default values {@link #DEFAULT_FORMAT_12_HOUR}
+ * and {@link #DEFAULT_FORMAT_24_HOUR} are used instead.
+ *
+ * @return true if time should be displayed in 24-hour format, false if it
+ * should be displayed in 12-hour format.
+ *
+ * @see #setFormat12Hour(CharSequence)
+ * @see #getFormat12Hour()
+ * @see #setFormat24Hour(CharSequence)
+ * @see #getFormat24Hour()
+ */
+ public boolean is24HourModeEnabled() {
+ return DateFormat.is24HourFormat(getContext());
+ }
+
+ /**
+ * Indicates which time zone is currently used by this view.
+ *
+ * @return The ID of the current time zone or null if the default time zone,
+ * as set by the user, must be used
+ *
+ * @see TimeZone
+ * @see java.util.TimeZone#getAvailableIDs()
+ * @see #setTimeZone(String)
+ */
+ public String getTimeZone() {
+ return mTimeZone;
+ }
+
+ /**
+ * Sets the specified time zone to use in this clock. When the time zone
+ * is set through this method, system time zone changes (when the user
+ * sets the time zone in settings for instance) will be ignored.
+ *
+ * @param timeZone The desired time zone's ID as specified in {@link TimeZone}
+ * or null to user the time zone specified by the user
+ * (system time zone)
+ *
+ * @see #getTimeZone()
+ * @see java.util.TimeZone#getAvailableIDs()
+ * @see TimeZone#getTimeZone(String)
+ *
+ * @attr ref android.R.styleable#TextClock_timeZone
+ */
+ public void setTimeZone(String timeZone) {
+ mTimeZone = timeZone;
+
+ createTime(timeZone);
+ onTimeChanged();
+ }
+
+ /**
+ * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
+ * depending on whether the user has selected 24-hour format.
+ *
+ * Calling this method does not schedule or unschedule the time ticker.
+ */
+ private void chooseFormat() {
+ chooseFormat(true);
+ }
+
+ /**
+ * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
+ * depending on whether the user has selected 24-hour format.
+ *
+ * @param handleTicker true if calling this method should schedule/unschedule the
+ * time ticker, false otherwise
+ */
+ private void chooseFormat(boolean handleTicker) {
+ final boolean format24Requested = is24HourModeEnabled();
+
+ if (format24Requested) {
+ mFormat = abc(mFormat24, mFormat12, DEFAULT_FORMAT_24_HOUR);
+ } else {
+ mFormat = abc(mFormat12, mFormat24, DEFAULT_FORMAT_12_HOUR);
+ }
+
+ boolean hadSeconds = mHasSeconds;
+ mHasSeconds = DateFormat.hasSeconds(mFormat);
+
+ if (handleTicker) {
+ if (hadSeconds != mHasSeconds) {
+ if (hadSeconds) getHandler().removeCallbacks(mTicker);
+ else mTicker.run();
+ }
+ }
+ }
+
+ /**
+ * Returns a if not null, else return b if not null, else return c.
+ */
+ private static CharSequence abc(CharSequence a, CharSequence b, CharSequence c) {
+ return a == null ? (b == null ? c : b) : a;
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ if (!mAttached) {
+ mAttached = true;
+
+ registerReceiver();
+ registerObserver();
+
+ createTime(mTimeZone);
+
+ if (mHasSeconds) {
+ mTicker.run();
+ } else {
+ onTimeChanged();
+ }
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ if (mAttached) {
+ unregisterReceiver();
+ unregisterObserver();
+
+ getHandler().removeCallbacks(mTicker);
+
+ mAttached = false;
+ }
+ }
+
+ private void registerReceiver() {
+ final IntentFilter filter = new IntentFilter();
+
+ filter.addAction(Intent.ACTION_TIME_TICK);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+
+ getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
+ }
+
+ private void registerObserver() {
+ final ContentResolver resolver = getContext().getContentResolver();
+ resolver.registerContentObserver(Settings.System.CONTENT_URI, true, mFormatChangeObserver);
+ }
+
+ private void unregisterReceiver() {
+ getContext().unregisterReceiver(mIntentReceiver);
+ }
+
+ private void unregisterObserver() {
+ final ContentResolver resolver = getContext().getContentResolver();
+ resolver.unregisterContentObserver(mFormatChangeObserver);
+ }
+
+ private void onTimeChanged() {
+ mTime.setTimeInMillis(System.currentTimeMillis());
+ setText(DateFormat.format(mFormat, mTime));
+ }
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f8c3b4d..3ee3c8c 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -129,6 +129,11 @@ public class LockPatternUtils {
*/
public static final int ID_DEFAULT_STATUS_WIDGET = -2;
+ /**
+ * Intent extra that's used to tag the default widget when using the picker
+ */
+ public static final String EXTRA_DEFAULT_WIDGET = "com.android.settings.DEFAULT_WIDGET";
+
protected final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
protected final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
protected final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 92aa06a..3f20ed1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -503,14 +503,16 @@
android:permissionGroupFlags="personalInfo"
android:priority="330" />
- <!-- Allows an application to access fine (e.g., GPS) location -->
+ <!-- Allows an app to access precise location from location sources such
+ as GPS, cell towers, and Wi-Fi. -->
<permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:permissionGroup="android.permission-group.LOCATION"
android:protectionLevel="dangerous"
android:label="@string/permlab_accessFineLocation"
android:description="@string/permdesc_accessFineLocation" />
- <!-- Allows an application to access coarse (e.g., Cell-ID, WiFi) location -->
+ <!-- Allows an app to access approximate location derived from network location
+ sources such as cell towers and Wi-Fi. -->
<permission android:name="android.permission.ACCESS_COARSE_LOCATION"
android:permissionGroup="android.permission-group.LOCATION"
android:protectionLevel="dangerous"
@@ -1901,6 +1903,13 @@
android:description="@string/permdesc_bindGadget"
android:protectionLevel="signature|system" />
+ <!-- Private permission, to restrict who can bring up a dialog to add a new
+ keyguard widget
+ @hide -->
+ <permission android:name="android.permission.BIND_KEYGUARD_APPWIDGET"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:protectionLevel="signature|system" />
+
<!-- Internal permission allowing an application to query/set which
applications can bind AppWidgets.
@hide -->
diff --git a/core/res/res/layout-port/keyguard_host_view.xml b/core/res/res/layout-port/keyguard_host_view.xml
index 5444471..a3c8105 100644
--- a/core/res/res/layout-port/keyguard_host_view.xml
+++ b/core/res/res/layout-port/keyguard_host_view.xml
@@ -36,7 +36,8 @@
<FrameLayout
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ androidprv:layout_childType="widgets">
<include layout="@layout/keyguard_widget_pager"
android:id="@+id/app_widget_container"
android:layout_width="match_parent"
@@ -51,12 +52,11 @@
<com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
android:id="@+id/keyguard_security_container"
- android:layout_width="@dimen/keyguard_security_width"
+ android:layout_width="wrap_content"
android:layout_height="@dimen/keyguard_security_height"
androidprv:layout_childType="challenge"
- android:layout_marginLeft="@dimen/kg_edge_swipe_region_size"
- android:layout_marginRight="@dimen/kg_edge_swipe_region_size"
android:background="@drawable/kg_bouncer_bg_white"
+ android:padding="0dp"
android:gravity="bottom|center_horizontal">
<com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
android:id="@+id/view_flipper"
@@ -64,9 +64,7 @@
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
- android:paddingLeft="@dimen/keyguard_security_view_margin"
android:paddingTop="@dimen/keyguard_security_view_margin"
- android:paddingRight="@dimen/keyguard_security_view_margin"
android:gravity="center">
</com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
</com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>
diff --git a/core/res/res/layout-port/keyguard_widget_pager.xml b/core/res/res/layout-port/keyguard_widget_pager.xml
index 3b29db8..7fd370b 100644
--- a/core/res/res/layout-port/keyguard_widget_pager.xml
+++ b/core/res/res/layout-port/keyguard_widget_pager.xml
@@ -25,7 +25,7 @@
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:paddingTop="25dp"
- android:paddingBottom="64dp"
+ android:paddingBottom="@dimen/kg_widget_pager_bottom_padding"
android:clipChildren="false"
android:clipToPadding="false"
androidprv:pageSpacing="10dp">
diff --git a/core/res/res/layout/keyguard_pin_view.xml b/core/res/res/layout/keyguard_pin_view.xml
index 19e0a27..2529196 100644
--- a/core/res/res/layout/keyguard_pin_view.xml
+++ b/core/res/res/layout/keyguard_pin_view.xml
@@ -59,6 +59,7 @@
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:background="?android:attr/selectableItemBackground"
+ android:contentDescription="@string/keyboardview_keycode_delete"
/>
</LinearLayout>
<View
@@ -196,6 +197,7 @@
android:layout_height="match_parent"
android:layout_weight="1"
android:src="@drawable/sym_keyboard_return_holo"
+ android:contentDescription="@string/keyboardview_keycode_enter"
/>
</LinearLayout>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 07f62ed..36f2628 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -50,4 +50,10 @@
<!-- Space reserved at the bottom of secure views (pin/pattern/password/SIM pin/SIM puk) -->
<dimen name="kg_secure_padding_height">0dp</dimen>
+ <!-- Top padding for the widget pager -->
+ <dimen name="kg_widget_pager_top_padding">0dp</dimen>
+
+ <!-- Bottom padding for the widget pager -->
+ <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
+
</resources>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 0d01df4..52c230b 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -98,10 +98,10 @@
<dimen name="kg_widget_pager_horizontal_padding">24dp</dimen>
<!-- Top padding for the widget pager -->
- <dimen name="kg_widget_pager_top_padding">24dp</dimen>
+ <dimen name="kg_widget_pager_top_padding">0dp</dimen>
<!-- Bottom padding for the widget pager -->
- <dimen name="kg_widget_pager_bottom_padding">16dp</dimen>
+ <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
<!-- Top margin for the runway lights. We add a negative margin in large
devices to account for the widget pager padding -->
diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml
index ffb4e11..ccdb4be 100644
--- a/core/res/res/values-sw720dp/dimens.xml
+++ b/core/res/res/values-sw720dp/dimens.xml
@@ -91,10 +91,10 @@
<dimen name="kg_widget_pager_horizontal_padding">80dp</dimen>
<!-- Top padding for the widget pager -->
- <dimen name="kg_widget_pager_top_padding">32dp</dimen>
+ <dimen name="kg_widget_pager_top_padding">0dp</dimen>
<!-- Bottom padding for the widget pager -->
- <dimen name="kg_widget_pager_bottom_padding">36dp</dimen>
+ <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
<!-- Top margin for the runway lights. We add a negative margin in large
devices to account for the widget pager padding -->
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d186c4a..186c8b3 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3046,6 +3046,24 @@
<!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
<attr name="textAllCaps" format="boolean" />
</declare-styleable>
+ <declare-styleable name="TextClock">
+ <!-- Specifies the formatting pattern used to show the time and/or date
+ in 12-hour mode. Please refer to {@link android.text.format.DateFormat}
+ for a complete description of accepted formatting patterns.
+ The default pattern is "h:mm aa". -->
+ <attr name="format12Hour" format="string"/>
+ <!-- Specifies the formatting pattern used to show the time and/or date
+ in 24-hour mode. Please refer to {@link android.text.format.DateFormat}
+ for a complete description of accepted formatting patterns.
+ The default pattern is "k:mm". -->
+ <attr name="format24Hour" format="string"/>
+ <!-- Specifies the time zone to use. When this attribute is specified, the
+ TextClock will ignore the time zone of the system. To use the user's
+ time zone, do not specify this attribute. The default value is the
+ user's time zone. Please refer to {@link java.util.TimeZone} for more
+ information about time zone ids. -->
+ <attr name="timeZone" format="string"/>
+ </declare-styleable>
<declare-styleable name="TextSwitcher">
</declare-styleable>
<declare-styleable name="TextView">
@@ -5798,6 +5816,8 @@
<!-- Scrim. This will block access to child views that
come before it in the child list in bouncer mode. -->
<enum name="scrim" value="4" />
+ <!-- The home for widgets. All widgets will be descendents of this. -->
+ <enum name="widgets" value="5" />
</attr>
<declare-styleable name="SlidingChallengeLayout">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0890a18..148560a 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -650,9 +650,9 @@
speech -->
<bool name="config_bluetooth_wide_band_speech">true</bool>
- <!-- Boolean indicating if current platform supports quick switch-on/off of
- Bluetooth Module -->
- <bool name="config_bluetooth_adapter_quick_switch">true</bool>
+ <!-- Boolean indicating if current platform need do one-time bluetooth address
+ re-validation -->
+ <bool name="config_bluetooth_address_validation">false</bool>
<!-- The default data-use polling period. -->
<integer name="config_datause_polling_period_sec">600</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c0b2b1f..4966b97 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -294,7 +294,7 @@
<dimen name="kg_widget_pager_top_padding">0dp</dimen>
<!-- Bottom padding for the widget pager -->
- <dimen name="kg_widget_pager_bottom_padding">0dp</dimen>
+ <dimen name="kg_widget_pager_bottom_padding">64dp</dimen>
<!-- Top margin for the runway lights. We add a negative margin in large
devices to account for the widget pager padding -->
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
index d1df2a4..053fc85 100644
--- a/core/res/res/values/integers.xml
+++ b/core/res/res/values/integers.xml
@@ -18,7 +18,7 @@
-->
<resources>
<integer name="kg_carousel_angle">75</integer>
- <integer name="kg_security_flip_duration">75</integer>
- <integer name="kg_security_fade_duration">75</integer>
+ <integer name="kg_security_flip_duration">100</integer>
+ <integer name="kg_security_fade_duration">100</integer>
<integer name="kg_glowpad_rotation_offset">0</integer>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d7a480b..06d3110 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2020,6 +2020,9 @@
<public type="attr" name="permissionFlags" id="0x010103c7" />
<public type="attr" name="checkedTextViewStyle" id="0x010103c8" />
<public type="attr" name="showOnLockScreen" id="0x010103c9" />
+ <public type="attr" name="format12Hour" id="0x010103ca" />
+ <public type="attr" name="format24Hour" id="0x010103cb" />
+ <public type="attr" name="timeZone" id="0x010103cc" />
<public type="style" name="Widget.Holo.CheckedTextView" id="0x010301d9" />
<public type="style" name="Widget.Holo.Light.CheckedTextView" id="0x010301da" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 159eec1..51d6429 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2065,6 +2065,15 @@
<!-- This can be used in any application wanting to disable the text "Emergency number" -->
<string name="emergency_call_dialog_number_for_display">Emergency number</string>
+ <!-- String to display if the clock status widget is selected (it is the default) [CHAR LIMIT=22] -->
+ <string name="widget_default" msgid="8269383575996003796">Clock</string>
+
+ <!-- Package name for default widget [DO NOT TRANSLATE] -->
+ <string name="widget_default_package_name">com.android.deskclock</string>
+
+ <!-- Class name for default widget [DO NOT TRANSLATE] -->
+ <string name="widget_default_class_name">com.android.deskclock.DeskClock</string>
+
<!--
*** touch based lock / unlock ***
--> <skip />
@@ -2276,14 +2285,12 @@
<string name="keyguard_accessibility_add_widget">Add widget.</string>
<!-- Accessibility description of the empty sidget slot (place holder for a new widget). [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_widget_empty_slot">Empty</string>
- <!-- Accessibility description of the unlock area. [CHAR_LIMIT=none] -->
- <string name="keyguard_accessibility_unlock_area">Unlock area.</string>
<!-- Accessibility description of the event of expanding an unlock area. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_unlock_area_expanded">Unlock area expanded.</string>
<!-- Accessibility description of the event of collapsing an unlock area. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_unlock_area_collapsed">Unlock area collapsed.</string>
<!-- Accessibility description of a lock screen widget. [CHAR_LIMIT=none] -->
- <string name="keyguard_accessibility_widget">%1$s widget.</string>
+ <string name="keyguard_accessibility_widget"><xliff:g id="widget_index">%1$s</xliff:g> widget.</string>
<!-- Accessibility description of the lock screen user selector widget. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_user_selector">User selector</string>
<!-- Accessibility description of the lock screen status widget. [CHAR_LIMIT=none] -->
@@ -2292,6 +2299,28 @@
<string name="keyguard_accessibility_camera">Camera</string>
<!-- Accessibility description of the lock media control widget. [CHAR_LIMIT=none] -->
<string name="keygaurd_accessibility_media_controls">Media controls</string>
+ <!-- Accessibility description of widget reordering start. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_widget_reorder_start">Widget reordering started.</string>
+ <!-- Accessibility description of widget reordering end. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_widget_reorder_end">Widget reordering ended.</string>
+ <!-- Accessibility description of the a widget deletion event. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_widget_deleted">Widget <xliff:g id="widget_index">%1$s</xliff:g> deleted.</string>
+ <!-- Accessibility description of the button to expand the lock area. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_expand_lock_area">Expand unlock area.</string>
+ <!-- Accessibility description of the slide unlock. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_slide_unlock">Slide unlock.</string>
+ <!-- Accessibility description of the pattern unlock. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_pattern_unlock">Pattern unlock.</string>
+ <!-- Accessibility description of the face unlock. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_face_unlock">Face unlock.</string>
+ <!-- Accessibility description of the pin lock. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_pin_unlock">Pin unlock.</string>
+ <!-- Accessibility description of the password lock. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_password_unlock">Password unlock.</string>
+ <!-- Accessibility description of the unlock pattern area. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_pattern_area">Pattern area.</string>
+ <!-- Accessibility description of the unlock slide area. [CHAR_LIMIT=none] -->
+ <string name="keyguard_accessibility_slide_area">Slide area.</string>
<!-- Password keyboard strings. Used by LockScreen and Settings --><skip />
<!-- Label for "switch to symbols" key. Must be short to fit on key! -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5a0088c..e820ace 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -245,7 +245,7 @@
<java-symbol type="bool" name="action_bar_embed_tabs_pre_jb" />
<java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
<java-symbol type="bool" name="config_allowActionMenuItemTextWithIcon" />
- <java-symbol type="bool" name="config_bluetooth_adapter_quick_switch" />
+ <java-symbol type="bool" name="config_bluetooth_address_validation" />
<java-symbol type="bool" name="config_bluetooth_sco_off_call" />
<java-symbol type="bool" name="config_cellBroadcastAppLinks" />
<java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
@@ -479,6 +479,9 @@
<java-symbol type="string" name="emailTypeOther" />
<java-symbol type="string" name="emailTypeWork" />
<java-symbol type="string" name="emergency_call_dialog_number_for_display" />
+ <java-symbol type="string" name="widget_default" />
+ <java-symbol type="string" name="widget_default_package_name" />
+ <java-symbol type="string" name="widget_default_class_name" />
<java-symbol type="string" name="emergency_calls_only" />
<java-symbol type="string" name="enable_accessibility_canceled" />
<java-symbol type="string" name="eventTypeAnniversary" />
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index 1bbc7df..5db7ffc 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -74,4 +74,5 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INJECT_EVENTS" />
</manifest>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 561e33e..245f537 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -65,6 +65,8 @@ public class ConnectivityManagerTestActivity extends Activity {
public static final long LONG_TIMEOUT = 50 * 1000;
// 2 minutes timer between wifi stop and start
public static final long WIFI_STOP_START_INTERVAL = 2 * 60 * 1000;
+ // Set ping test timer to be 3 minutes
+ public static final long PING_TIMER = 3 * 60 *1000;
public static final int SUCCESS = 0; // for Wifi tethering state change
public static final int FAILURE = 1;
public static final int INIT = -1;
@@ -517,37 +519,36 @@ public class ConnectivityManagerTestActivity extends Activity {
* @return true if the ping test is successful, false otherwise.
*/
public boolean pingTest(String[] pingServerList) {
- boolean result = false;
String[] hostList = {"www.google.com", "www.yahoo.com",
"www.bing.com", "www.facebook.com", "www.ask.com"};
if (pingServerList != null) {
hostList = pingServerList;
}
- try {
- // assume the chance that all servers are down is very small
- for (int i = 0; i < hostList.length; i++ ) {
- String host = hostList[i];
- log("Start ping test, ping " + host);
- Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
- int status = p.waitFor();
- if (status == 0) {
- // if any of the ping test is successful, return true
- result = true;
- break;
- } else {
- result = false;
- log("ping " + host + " failed.");
+
+ long startTime = System.currentTimeMillis();
+ while ((System.currentTimeMillis() - startTime) < PING_TIMER) {
+ try {
+ // assume the chance that all servers are down is very small
+ for (int i = 0; i < hostList.length; i++ ) {
+ String host = hostList[i];
+ log("Start ping test, ping " + host);
+ Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
+ int status = p.waitFor();
+ if (status == 0) {
+ // if any of the ping test is successful, return true
+ return true;
+ }
}
+ } catch (UnknownHostException e) {
+ log("Ping test Fail: Unknown Host");
+ } catch (IOException e) {
+ log("Ping test Fail: IOException");
+ } catch (InterruptedException e) {
+ log("Ping test Fail: InterruptedException");
}
- } catch (UnknownHostException e) {
- log("Ping test Fail: Unknown Host");
- } catch (IOException e) {
- log("Ping test Fail: IOException");
- } catch (InterruptedException e) {
- log("Ping test Fail: InterruptedException");
}
- log("return");
- return result;
+ // ping test timeout
+ return false;
}
/**
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 79d928c..7bfb594 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -28,6 +28,7 @@ import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.PowerManager;
import android.provider.Settings;
+import android.view.KeyEvent;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
@@ -289,6 +290,11 @@ public class WifiStressTest
// Turn screen on again
mAct.turnScreenOn();
+ // Wait for 2 seconds for the lock screen
+ sleep(2 * 1000, "wait 2 seconds for lock screen");
+ // Disable lock screen by inject menu key event
+ mRunner.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
+
// Measure the time for Wi-Fi to get connected
long startTime = System.currentTimeMillis();
assertTrue("Wait for Wi-Fi enable timeout after wake up",
diff --git a/docs/html/guide/google/play/expansion-files.jd b/docs/html/guide/google/play/expansion-files.jd
index 750e958..f5cda06 100644
--- a/docs/html/guide/google/play/expansion-files.jd
+++ b/docs/html/guide/google/play/expansion-files.jd
@@ -421,7 +421,7 @@ policy, which captures the expansion file names, sizes, and URLs from the licens
<p>To use APK expansion files with your application and provide the best user experience with
minimal effort on your behalf, we recommend you use the Downloader Library that's included in the
-Google Market Apk Expansion package. This library downloads your expansion files in a
+Google Play APK Expansion Library package. This library downloads your expansion files in a
background service, shows a user notification with the download status, handles network
connectivity loss, resumes the download when possible, and more.</p>
@@ -450,8 +450,8 @@ application.</p>
<p>First, open the <a href="{@docRoot}sdk/exploring.html">Android SDK Manager</a>, expand
<em>Extras</em> and download:</p>
<ul>
- <li><em>Google Market Licensing package</em></li>
- <li><em>Google Market Apk Expansion package</em></li>
+ <li><em>Google Play Licensing Library package</em></li>
+ <li><em>Google Play APK Expansion Library package</em></li>
</ul>
<p>If you're using Eclipse, create a project for each library and add it to your app:</p>
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index 2de6260..8026b7d 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -18,6 +18,7 @@ page.title=Notifications
<li><a href="#Actions">Notification actions</a></li>
<li><a href="#SimpleNotification">Creating a simple notification</a></li>
<li><a href="#ApplyStyle">Applying a big view style to a notification</a></li>
+ <li><a href="#Compatibility">Handling compatibility</a></li>
</ol>
</li>
<li><a href="#Managing">Managing Notifications</a>
@@ -91,18 +92,36 @@ page.title=Notifications
</p>
</div>
<p class="note">
- <strong>Note:</strong> This guide refers to the
+ <strong>Note:</strong> Except where noted, this guide refers to the
{@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} class
in the version 4 <a href="{@docRoot}tools/extras/support-library.html">Support Library</a>.
- The class {@link android.app.Notification.Builder Notification.Builder} was added in API
- level 11.
+ The class {@link android.app.Notification.Builder Notification.Builder} was added in Android
+ 3.0.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="NotificationUI">Notification Display Elements</h2>
<p>
- Notifications in the notification drawer appear in two main visual styles, normal view and
- big view.
+ Notifications in the notification drawer can appear in one of two visual styles, depending on
+ the version and the state of the drawer:
+</p>
+<dl>
+ <dt>
+ Normal view
+ </dt>
+ <dd>
+ The standard view of the notifications in the notification drawer.
+ </dd>
+ <dt>
+ Big view
+ </dt>
+ <dd>
+ A large view that's visible when the notification is expanded. Big view is part of the
+ expanded notification feature available as of Android 4.1.
+ </dd>
+</dl>
+<p>
+ These styles are described in the following sections.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="NormalNotify">Normal view</h3>
@@ -139,7 +158,7 @@ page.title=Notifications
<p>
A notification's big view appears only when the notification is expanded, which happens when the
notification is at the top of the notification drawer, or when the user expands the
- notification with a gesture.
+ notification with a gesture. Expanded notifications are available starting with Android 4.1.
</p>
<p>
The following screenshot shows an inbox-style notification:
@@ -246,10 +265,12 @@ page.title=Notifications
</p>
<p>
A notification can provide multiple actions. You should always define the action that's
- triggered when the user touches the notification; usually this action opens an
+ triggered when the user clicks the notification; usually this action opens an
{@link android.app.Activity} in your application. You can also add buttons to the notification
that perform additional actions such as snoozing an alarm or responding immediately to a text
- message.
+ message; this feature is available as of Android 4.1. If you use additional action buttons, you
+ must also make their functionality available in an {@link android.app.Activity} in your app; see
+ the section <a href="#Compatibility">Handling compatibility</a> for more details.
</p>
<p>
Inside a {@link android.app.Notification}, the action itself is defined by a
@@ -257,22 +278,22 @@ page.title=Notifications
an {@link android.app.Activity} in your application. To associate the
{@link android.app.PendingIntent} with a gesture, call the appropriate method of
{@link android.support.v4.app.NotificationCompat.Builder}. For example, if you want to start
- {@link android.app.Activity} when the user touches the notification text in
+ {@link android.app.Activity} when the user clicks the notification text in
the notification drawer, you add the {@link android.app.PendingIntent} by calling
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
</p>
<p>
- Starting an {@link android.app.Activity} when the user touches the notification is the most
+ Starting an {@link android.app.Activity} when the user clicks the notification is the most
common action scenario. You can also start an {@link android.app.Activity} when the user
- dismisses an {@link android.app.Activity}, and you can start an {@link android.app.Activity}
- from an action button. To learn more, read the reference guide for
+ dismisses an {@link android.app.Activity}. In Android 4.1 and later, you can start an
+ {@link android.app.Activity} from an action button. To learn more, read the reference guide for
{@link android.support.v4.app.NotificationCompat.Builder}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="SimpleNotification">Creating a simple notification</h3>
<p>
The following snippet illustrates a simple notification that specifies an activity to open when
- the user touches the notification. Notice that the code creates a
+ the user clicks the notification. Notice that the code creates a
{@link android.support.v4.app.TaskStackBuilder} object and uses it to create the
{@link android.app.PendingIntent} for the action. This pattern is explained in more detail
in the section <a href="#NotificationResponse">
@@ -317,6 +338,11 @@ mNotificationManager.notify(mId, mBuilder.build());
Builder.setStyle()} with a big view style object as its argument.
</p>
<p>
+ Remember that expanded notifications are not available on platforms prior to Android 4.1. To
+ learn how to handle notifications for Android 4.1 and for earlier platforms, read the
+ section <a href="#Compatibility">Handling compatibility</a>.
+</p>
+<p>
For example, the following code snippet demonstrates how to alter the notification created
in the previous snippet to use the Inbox big view style:
</p>
@@ -341,6 +367,47 @@ mBuilder.setStyle(inBoxStyle);
...
// Issue the notification here.
</pre>
+<h3 id="Compatibility">Handling compatibility</h3>
+<p>
+ Not all notification features are available for a particular version, even though
+ the methods to set them are in the support library class
+ {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
+ For example, action buttons, which depend on expanded notifications, only appear on Android
+ 4.1 and higher, because expanded notifications themselves are only available on
+ Android 4.1 and higher.
+</p>
+<p>
+ To ensure the best compatibility, create notifications with
+ {@link android.support.v4.app.NotificationCompat NotificationCompat} and its subclasses,
+ particularly {@link android.support.v4.app.NotificationCompat.Builder
+ NotificationCompat.Builder}. In addition, follow this process when you implement a notification:
+</p>
+<ol>
+ <li>
+ Provide all of the notification's functionality to all users, regardless of the version
+ they're using. To do this, verify that all of the functionality is available from an
+ {@link android.app.Activity} in your app. You may want to add a new
+ {@link android.app.Activity} to do this.
+ <p>
+ For example, if you want to use
+ {@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} to
+ provide a control that stops and starts media playback, first implement this
+ control in an {@link android.app.Activity} in your app.
+ </p>
+ </li>
+ <li>
+ Ensure that all users can get to the functionality in the {@link android.app.Activity},
+ by having it start when users click the notification. To do this,
+ create a {@link android.app.PendingIntent} for the {@link android.app.Activity}. Call
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+ setContentIntent()} to add the {@link android.app.PendingIntent} to the notification.
+ </li>
+ <li>
+ Now add the expanded notification features you want to use to the notification. Remember
+ that any functionality you add also has to be available in the {@link android.app.Activity}
+ that starts when users click the notification.
+ </li>
+</ol>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="Managing">Managing Notifications</h2>
@@ -355,6 +422,10 @@ mBuilder.setStyle(inBoxStyle);
"stacking" the notification; it's described in more detail in the
<a href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design guide.
</p>
+<p class="note">
+ <strong>Note:</strong> This Gmail feature requires the "inbox" big view style, which is
+ part of the expanded notification feature available starting in Android 4.1.
+</p>
<p>
The following section describes how to update notifications and also how to remove them.
</p>
@@ -417,7 +488,7 @@ numMessages = 0;
the notification can be cleared).
</li>
<li>
- The user touches the notification, and you called
+ The user clicks the notification, and you called
{@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} when
you created the notification.
</li>
@@ -452,7 +523,7 @@ numMessages = 0;
start a fresh task, and provide the {@link android.app.PendingIntent} with a back stack
that reproduces the application's normal <i>Back</i> behavior.
<p>
- Notifications from the Gmail app demonstrate this. When you touch a notification for
+ Notifications from the Gmail app demonstrate this. When you click a notification for
a single email message, you see the message itself. Touching <b>Back</b> takes you
backwards through Gmail to the Home screen, just as if you had entered Gmail from the
Home screen rather than entering it from a notification.
@@ -489,7 +560,7 @@ numMessages = 0;
Define your application's {@link android.app.Activity} hierarchy in the manifest.
<ol style="list-style-type: lower-alpha;">
<li>
- Add support for API versions 15 and earlier. To do this, specify the parent of the
+ Add support for Android 4.0.3 and earlier. To do this, specify the parent of the
{@link android.app.Activity} you're starting by adding a
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
element as the child of the
@@ -507,7 +578,7 @@ numMessages = 0;
</p>
</li>
<li>
- Also add support for API versions 16 and later. To do this, add the
+ Also add support for Android 4.1 and later. To do this, add the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
attribute to the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
@@ -738,9 +809,14 @@ mNotificationManager.notify(id, builder.build());
{@link android.widget.ProgressBar} class.
</p>
<p>
- To use a progress indicator, call
- {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. The
- determinate and indeterminate forms are described in the following sections.
+ To use a progress indicator on platforms starting with Android 4.0, call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. For
+ previous versions, you must create your own custom notification layout that
+ includes a {@link android.widget.ProgressBar} view.
+</p>
+<p>
+ The following sections describe how to display progress in a notification using
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="FixedProgress">Displaying a fixed-duration progress indicator</h3>
@@ -872,6 +948,10 @@ mNotifyManager.notify(0, mBuilder.build());
{@link android.widget.RemoteViews} defined in a XML layout file.
</p>
<p>
+ The height available for a custom notification layout depends on the notification view. Normal
+ view layouts are limited to 64 dp, and expanded view layouts are limited to 256 dp.
+</p>
+<p>
To define a custom notification layout, start by instantiating a
{@link android.widget.RemoteViews} object that inflates an XML layout file. Then,
instead of calling methods such as
@@ -911,8 +991,8 @@ mNotifyManager.notify(0, mBuilder.build());
<h4>Using style resources for custom notification text</h4>
<p>
Always use style resources for the text of a custom notification. The background color of the
- notification can vary across different devices and platform versions, and using style resources
- helps you account for this. Starting in API level 9, the system defined a style for the
- standard notification layout text. If you use the same style in applications that target API
- level 9 or higher, you'll ensure that your text is visible against the display background.
+ notification can vary across different devices and versions, and using style resources
+ helps you account for this. Starting in Android 2.3, the system defined a style for the
+ standard notification layout text. If you use the same style in applications that target Android
+ 2.3 or higher, you'll ensure that your text is visible against the display background.
</p>
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 8374b10..0623a9e 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -1191,6 +1191,11 @@ public class GradientDrawable extends Drawable {
return;
}
+ if (mRadius > 0 || mRadiusArray != null) {
+ mOpaque = false;
+ return;
+ }
+
if (mStrokeWidth > 0 && !isOpaque(mStrokeColor)) {
mOpaque = false;
return;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e2d7156..6787705 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2433,7 +2433,7 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto
}
// TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
- if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || p->getStrokeCap() != SkPaint::kButt_Cap) {
+ if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || p->getStrokeCap() != SkPaint::kButt_Cap || useCenter) {
mCaches.activeTexture(0);
const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top,
startAngle, sweepAngle, useCenter, p);
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
index b3e4a88..791d3d0 100644
--- a/location/java/android/location/Geofence.java
+++ b/location/java/android/location/Geofence.java
@@ -22,7 +22,7 @@ import android.os.Parcelable;
/**
* Represents a geographical boundary, also known as a geofence.
*
- * <p>Currently only circular geofences are supported.
+ * <p>Currently only circular geofences are supported and they do not support altitude changes.
*/
public final class Geofence implements Parcelable {
/** @hide */
@@ -34,7 +34,7 @@ public final class Geofence implements Parcelable {
private final float mRadius;
/**
- * Create a horizontal, circular geofence.
+ * Create a circular geofence (on a flat, horizontal plane).
*
* @param latitude latitude in degrees
* @param longitude longitude in degrees
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 59a5624..653e8d1 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -811,6 +811,10 @@ public class LocationManager {
/**
* Register for fused location updates using a LocationRequest and callback.
*
+ * <p>Upon a location update, the system delivers the new {@link Location} to the
+ * provided {@link LocationListener}, by calling its {@link
+ * LocationListener#onLocationChanged} method.</p>
+ *
* <p>The system will automatically select and enable the best providers
* to compute a location for your application. It may use only passive
* locations, or just a single location source, or it may fuse together
@@ -869,6 +873,10 @@ public class LocationManager {
/**
* Register for fused location updates using a LocationRequest and a pending intent.
*
+ * <p>Upon a location update, the system delivers the new {@link Location} with your provided
+ * {@link PendingIntent}, as the value for {@link LocationManager#KEY_LOCATION_CHANGED}
+ * in the intent's extras.</p>
+ *
* <p> To unregister for Location updates, use: {@link #removeUpdates(PendingIntent)}.
*
* <p> See {@link #requestLocationUpdates(LocationRequest, LocationListener, Looper)}
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index c34ca3e..7f7a51c 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -174,7 +174,7 @@
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skærmen er nu låst i liggende retning."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skærmen er nu låst i stående retning."</string>
<string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
- <string name="start_dreams" msgid="7219575858348719790">"Dagdrømme"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flytilstand"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Oplader, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index d5af0cd..d619de1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -176,7 +176,7 @@
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
<string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
- <string name="start_dreams" msgid="7219575858348719790">"Activar Daydreams"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Activar protector"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo de avión"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index e8bc08d..19de9b6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -174,7 +174,7 @@
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
<string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
- <string name="start_dreams" msgid="7219575858348719790">"Suspender"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Salvapantallas"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a12ccf0..babbcce 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -176,7 +176,7 @@
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"L\'écran est verrouillé en mode paysage."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"L\'écran est verrouillé en mode portrait."</string>
<string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
- <string name="start_dreams" msgid="7219575858348719790">"Écran de veille"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Écran de veille interactif"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode avion"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index a05aa8f..c454bb1 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -174,7 +174,7 @@
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekran jest zablokowany w orientacji poziomej."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekran jest zablokowany w orientacji pionowej."</string>
<string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
- <string name="start_dreams" msgid="7219575858348719790">"Śnij na jawie"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Wygaszacz ekranu"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Tryb samolotowy"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 1ca085c..1b8370b 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -174,7 +174,7 @@
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"O ecrã está bloqueado na orientação horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"O ecrã está bloqueado na orientação vertical."</string>
<string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
- <string name="start_dreams" msgid="7219575858348719790">"Sonho"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo de avião"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"A carregar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index fba3da5..7e2d030 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -172,7 +172,7 @@
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skrini imefungwa sasa katika uelekezo wa mandhari."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Skrini imefungwa katika uelekeo wa picha."</string>
<string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
- <string name="start_dreams" msgid="7219575858348719790">"Ndoto ya mchana"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Hali Tulivu"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modi ya ndege"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Inachaji, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 17256cf..de028a4 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2965,10 +2965,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean applyWindow = attrs.type >= FIRST_APPLICATION_WINDOW
&& attrs.type <= LAST_APPLICATION_WINDOW;
if (attrs.type == TYPE_DREAM) {
- mShowingDream = true;
- if (!mDreamingLockscreen) {
- applyWindow = true;
- } else if (win.isVisibleLw() && win.hasDrawnLw()) {
+ // If the lockscreen was showing when the dream started then wait
+ // for the dream to draw before hiding the lockscreen.
+ if (!mDreamingLockscreen
+ || (win.isVisibleLw() && win.hasDrawnLw())) {
+ mShowingDream = true;
applyWindow = true;
}
}
@@ -3008,8 +3009,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
? mTopFullscreenOpaqueWindowState.getAttrs()
: null;
- // If we are not currently showing a dream, then update the lockscreen
- // state that will apply if a dream is shown next time.
+ // If we are not currently showing a dream then remember the current
+ // lockscreen state. We will use this to determine whether the dream
+ // started while the lockscreen was showing and remember this state
+ // while the dream is showing.
if (!mShowingDream) {
mDreamingLockscreen = mShowingLockscreen;
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
index eabf5e0..db36bcc 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
@@ -98,6 +98,9 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
mPasswordEntry.setOnEditorActionListener(this);
mPasswordEntry.addTextChangedListener(this);
+ // Set selected property on so the view can send accessibility events.
+ mPasswordEntry.setSelected(true);
+
// Poke the wakelock any time the text is selected or modified
mPasswordEntry.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index e929fb1..3b2ded2 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -25,19 +25,22 @@ import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.os.Bundle;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -54,6 +57,7 @@ import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityM
import com.android.internal.widget.LockPatternUtils;
import java.io.File;
+import java.util.ArrayList;
import java.util.List;
public class KeyguardHostView extends KeyguardViewBase {
@@ -670,13 +674,10 @@ public class KeyguardHostView extends KeyguardViewBase {
// Find and show this child.
final int childCount = mSecurityViewContainer.getChildCount();
- // Do flip animation to the next screen
- if (false) {
- mSecurityViewContainer.setInAnimation(
- AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_in));
- mSecurityViewContainer.setOutAnimation(
- AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_out));
- }
+ mSecurityViewContainer.setInAnimation(
+ AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_in));
+ mSecurityViewContainer.setOutAnimation(
+ AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_out));
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
for (int i = 0; i < childCount; i++) {
if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
@@ -883,14 +884,22 @@ public class KeyguardHostView extends KeyguardViewBase {
@Override
public void run() {
- Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
- intent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_SINGLE_TOP
- | Intent.FLAG_ACTIVITY_CLEAR_TOP
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- mContext.startActivityAsUser(intent,
- new UserHandle(UserHandle.USER_CURRENT));
+ int defaultIconId = 0;
+ Resources res = KeyguardHostView.this.getContext().getResources();
+ ComponentName clock = new ComponentName(
+ res.getString(R.string.widget_default_package_name),
+ res.getString(R.string.widget_default_class_name));
+ try {
+ ActivityInfo activityInfo =
+ mContext.getPackageManager().getActivityInfo(clock, 0);
+ if (activityInfo != null) {
+ defaultIconId = activityInfo.icon;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ defaultIconId = 0;
+ }
+ launchPickActivityIntent(R.string.widget_default, defaultIconId, clock,
+ LockPatternUtils.EXTRA_DEFAULT_WIDGET);
}
});
mCallback.dismiss(false);
@@ -901,6 +910,58 @@ public class KeyguardHostView extends KeyguardViewBase {
initializeTransportControl();
}
+ private void launchPickActivityIntent(int defaultLabelId, int defaultIconId,
+ ComponentName defaultComponentName, String defaultTag) {
+ // Create intent to pick widget
+ Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
+
+ int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+ if (appWidgetId != -1) {
+ pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+ pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
+ pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
+
+ // Add an custom entry for the default
+ AppWidgetProviderInfo defaultInfo = new AppWidgetProviderInfo();
+ ArrayList<AppWidgetProviderInfo> extraInfos = new ArrayList<AppWidgetProviderInfo>();
+ defaultInfo.label = getResources().getString(defaultLabelId);
+ defaultInfo.icon = defaultIconId;
+ defaultInfo.provider = defaultComponentName;
+ extraInfos.add(defaultInfo);
+
+ ArrayList<Bundle> extraExtras = new ArrayList<Bundle>();
+ Bundle b = new Bundle();
+ b.putBoolean(defaultTag, true);
+ extraExtras.add(b);
+
+ // Launch the widget picker
+ pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_INFO, extraInfos);
+ pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS, extraExtras);
+ pickIntent.putExtra(Intent.EXTRA_INTENT, getBaseIntent());
+ pickIntent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_SINGLE_TOP
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ mContext.startActivityAsUser(pickIntent,
+ new UserHandle(UserHandle.USER_CURRENT));
+ } else {
+ Log.e(TAG, "Unable to allocate an AppWidget id in lock screen");
+ }
+ }
+
+ private Intent getBaseIntent() {
+ Intent baseIntent = new Intent(Intent.ACTION_MAIN, null);
+ baseIntent.addCategory(Intent.CATEGORY_DEFAULT);
+
+ Bundle options = new Bundle();
+ options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
+ baseIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
+ return baseIntent;
+ }
+
private void removeTransportFromWidgetPager() {
int page = getWidgetPosition(R.id.keyguard_transport_control);
if (page != -1) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
index ca78cf9..5e331e1 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
@@ -16,6 +16,9 @@
package com.android.internal.policy.impl.keyguard;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Handler;
@@ -39,11 +42,15 @@ class KeyguardMessageArea extends TextView {
static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
static final int SECURITY_MESSAGE_DURATION = 5000;
- static final String SEPARATOR = " ";
+ protected static final int FADE_DURATION = 750;
+ static final String SEPARATOR = " ";
// are we showing battery information?
boolean mShowingBatteryInfo = false;
+ // is the bouncer up?
+ boolean mShowingBouncer = false;
+
// last known plugged in state
boolean mPluggedIn = false;
@@ -68,7 +75,11 @@ class KeyguardMessageArea extends TextView {
public void run() {
mMessage = null;
mShowingMessage = false;
- update();
+ if (mShowingBouncer) {
+ hideMessage(FADE_DURATION, true);
+ } else {
+ update();
+ }
}
};
@@ -103,6 +114,18 @@ class KeyguardMessageArea extends TextView {
}
@Override
+ public void showBouncer(int duration) {
+ mMessageArea.hideMessage(duration, false);
+ mMessageArea.mShowingBouncer = true;
+ }
+
+ @Override
+ public void hideBouncer(int duration) {
+ mMessageArea.showMessage(duration);
+ mMessageArea.mShowingBouncer = false;
+ }
+
+ @Override
public void setTimeout(int timeoutMs) {
mMessageArea.mTimeout = timeoutMs;
}
@@ -139,6 +162,7 @@ class KeyguardMessageArea extends TextView {
}
public void securityMessageChanged() {
+ setAlpha(1f);
mShowingMessage = true;
update();
mHandler.removeCallbacks(mClearMessageRunnable);
@@ -212,4 +236,23 @@ class KeyguardMessageArea extends TextView {
return string;
}
+ private void hideMessage(int duration, boolean thenUpdate) {
+ Animator anim = ObjectAnimator.ofFloat(this, "alpha", 0f);
+ anim.setDuration(duration);
+ if (thenUpdate) {
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ update();
+ }
+ });
+ }
+ anim.start();
+ }
+
+ private void showMessage(int duration) {
+ Animator anim = ObjectAnimator.ofFloat(this, "alpha", 1f);
+ anim.setDuration(duration);
+ anim.start();
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
index 8522401..1255712 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
@@ -64,6 +64,7 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView
verifyPasswordAndUnlock();
}
});
+ ok.setOnHoverListener(new NumPadKey.LiftToActivateListener(getContext()));
}
// The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java
index f6a90c5..04ab0a2 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java
@@ -1,11 +1,20 @@
package com.android.internal.policy.impl.keyguard;
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.FrameLayout;
+import com.android.internal.R;
+
public class KeyguardSecurityContainer extends FrameLayout {
+ private float mBackgroundAlpha;
+ private Drawable mBackgroundDrawable;
+
public KeyguardSecurityContainer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -16,5 +25,44 @@ public class KeyguardSecurityContainer extends FrameLayout {
public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ mBackgroundDrawable = context.getResources().getDrawable(R.drawable.kg_bouncer_bg_white);
+ }
+
+ public void setBackgroundAlpha(float alpha) {
+ if (Float.compare(mBackgroundAlpha, alpha) != 0) {
+ mBackgroundAlpha = alpha;
+ invalidate();
+ }
+ }
+
+ public float getBackgroundAlpha() {
+ return mBackgroundAlpha;
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ if (mBackgroundAlpha > 0.0f && mBackgroundDrawable != null) {
+ Drawable bg = mBackgroundDrawable;
+ bg.setAlpha((int) (mBackgroundAlpha * 255));
+ bg.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ bg.draw(canvas);
+ }
+ super.dispatchDraw(canvas);
+ }
+
+ public void showBouncer(int duration) {
+ SecurityMessageDisplay message = new KeyguardMessageArea.Helper(this);
+ message.showBouncer(duration);
+ Animator anim = ObjectAnimator.ofFloat(this, "BackgroundAlpha", 1f);
+ anim.setDuration(duration);
+ anim.start();
+ }
+
+ public void hideBouncer(int duration) {
+ SecurityMessageDisplay message = new KeyguardMessageArea.Helper(this);
+ message.hideBouncer(duration);
+ Animator anim = ObjectAnimator.ofFloat(this, "BackgroundAlpha", 0f);
+ anim.setDuration(duration);
+ anim.start();
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
index b4bd6e9..7100f1c 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java
@@ -327,6 +327,14 @@ class KeyguardStatusViewManager implements SecurityMessageDisplay {
}
@Override
+ public void showBouncer(int duration) {
+ }
+
+ @Override
+ public void hideBouncer(int duration) {
+ }
+
+ @Override
public void setTimeout(int timeout_ms) {
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java
index a207f5d..b38eb28 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java
@@ -16,6 +16,10 @@
package com.android.internal.policy.impl.keyguard;
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
@@ -35,8 +39,9 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
public static final int VERTICAL = LinearLayout.VERTICAL;
+ protected static final int ANIMATE_BOUNCE_DURATION = 750;
- private View mChallengeView;
+ private KeyguardSecurityContainer mChallengeView;
private View mUserSwitcherView;
private View mScrimView;
private OnBouncerStateChangedListener mBouncerListener;
@@ -87,7 +92,19 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
if (mIsBouncing) return;
mIsBouncing = true;
if (mScrimView != null) {
- mScrimView.setVisibility(GONE);
+ if (mChallengeView != null) {
+ mChallengeView.showBouncer(ANIMATE_BOUNCE_DURATION);
+ }
+
+ Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 1f);
+ anim.setDuration(ANIMATE_BOUNCE_DURATION);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mScrimView.setVisibility(VISIBLE);
+ }
+ });
+ anim.start();
}
if (mBouncerListener != null) {
mBouncerListener.onBouncerStateChanged(true);
@@ -99,7 +116,19 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
if (!mIsBouncing) return;
mIsBouncing = false;
if (mScrimView != null) {
- mScrimView.setVisibility(GONE);
+ if (mChallengeView != null) {
+ mChallengeView.hideBouncer(ANIMATE_BOUNCE_DURATION);
+ }
+
+ Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 0f);
+ anim.setDuration(ANIMATE_BOUNCE_DURATION);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mScrimView.setVisibility(INVISIBLE);
+ }
+ });
+ anim.start();
}
if (mBouncerListener != null) {
mBouncerListener.onBouncerStateChanged(false);
@@ -131,7 +160,8 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
mScrimView.setOnClickListener(null);
}
mScrimView = scrim;
- mScrimView.setVisibility(mIsBouncing ? VISIBLE : GONE);
+ mScrimView.setAlpha(mIsBouncing ? 1.0f : 0.0f);
+ mScrimView.setVisibility(mIsBouncing ? VISIBLE : INVISIBLE);
mScrimView.setFocusable(true);
mScrimView.setOnClickListener(mScrimClickListener);
}
@@ -165,7 +195,11 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
throw new IllegalStateException(
"There may only be one child of type challenge");
}
- mChallengeView = child;
+ if (!(child instanceof KeyguardSecurityContainer)) {
+ throw new IllegalArgumentException(
+ "Challenge must be a KeyguardSecurityContainer");
+ }
+ mChallengeView = (KeyguardSecurityContainer) child;
} else if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER) {
if (mUserSwitcherView != null) {
throw new IllegalStateException(
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java b/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
index 060cc03..ca36007 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
@@ -22,7 +22,9 @@ import android.text.SpannableStringBuilder;
import android.text.style.TextAppearanceSpan;
import android.util.AttributeSet;
import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityManager;
import android.widget.Button;
import android.widget.TextView;
@@ -72,6 +74,7 @@ public class NumPadKey extends Button {
setTextViewResId(a.getResourceId(R.styleable.NumPadKey_textView, 0));
setOnClickListener(mListener);
+ setOnHoverListener(new LiftToActivateListener(context));
mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled();
@@ -113,4 +116,45 @@ public class NumPadKey extends Button {
| HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
}
}
+
+ /**
+ * Hover listener that implements lift-to-activate interaction for
+ * accessibility. May be added to multiple views.
+ */
+ static class LiftToActivateListener implements View.OnHoverListener {
+ /** Manager used to query accessibility enabled state. */
+ private final AccessibilityManager mAccessibilityManager;
+
+ public LiftToActivateListener(Context context) {
+ mAccessibilityManager = (AccessibilityManager) context.getSystemService(
+ Context.ACCESSIBILITY_SERVICE);
+ }
+
+ @Override
+ public boolean onHover(View v, MotionEvent event) {
+ // When touch exploration is turned on, lifting a finger while
+ // inside the view bounds should perform a click action.
+ if (mAccessibilityManager.isEnabled()
+ && mAccessibilityManager.isTouchExplorationEnabled()) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ // Lift-to-type temporarily disables double-tap
+ // activation.
+ v.setClickable(false);
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ final int x = (int) event.getX();
+ final int y = (int) event.getY();
+ if ((x > v.getPaddingLeft()) && (y > v.getPaddingTop())
+ && (x < v.getWidth() - v.getPaddingRight())
+ && (y < v.getHeight() - v.getPaddingBottom())) {
+ v.performClick();
+ }
+ v.setClickable(true);
+ break;
+ }
+ }
+ return false;
+ }
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java b/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java
index ec6472f..7760279 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java
@@ -24,4 +24,8 @@ public interface SecurityMessageDisplay {
public void setMessage(int resId, boolean important, Object... formatArgs);
public void setTimeout(int timeout_ms);
+
+ public void showBouncer(int animationDuration);
+
+ public void hideBouncer(int animationDuration);
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
index 74b05dd..2e735a0 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
@@ -16,11 +16,15 @@
package com.android.internal.policy.impl.keyguard;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.FloatProperty;
@@ -61,10 +65,12 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
private Drawable mHandleDrawable;
private Drawable mFrameDrawable;
private Drawable mDragIconDrawable;
+ private boolean mEdgeCaptured;
// Initialized during measurement from child layoutparams
private View mChallengeView;
private View mScrimView;
+ private View mWidgetsView;
// Range: 0 (fully hidden) to 1 (fully visible)
private float mChallengeOffset = 1.f;
@@ -110,9 +116,14 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
float mHandleAlpha;
float mFrameAlpha;
+ float mFrameAnimationTarget = Float.MIN_VALUE;
private ObjectAnimator mHandleAnimation;
private ObjectAnimator mFrameAnimation;
+ private final Rect mTempRect = new Rect();
+
+ private boolean mHasGlowpad;
+
static final Property<SlidingChallengeLayout, Float> HANDLE_ALPHA =
new FloatProperty<SlidingChallengeLayout>("handleAlpha") {
@Override
@@ -237,12 +248,12 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
mMinVelocity = vc.getScaledMinimumFlingVelocity();
mMaxVelocity = vc.getScaledMaximumFlingVelocity();
- mDragHandleEdgeSlop = getResources().getDimensionPixelSize(
- R.dimen.kg_edge_swipe_region_size);
+ final Resources res = getResources();
+ mDragHandleEdgeSlop = res.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
- final float density = getResources().getDisplayMetrics().density;
+ final float density = res.getDisplayMetrics().density;
// top half of the lock icon, plus another 25% to be sure
mDragHandleClosedAbove = (int) (DRAG_HANDLE_CLOSED_ABOVE * density + 0.5f);
@@ -251,7 +262,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
mDragHandleOpenBelow = (int) (DRAG_HANDLE_OPEN_BELOW * density + 0.5f);
// how much space to account for in the handle when closed
- mChallengeBottomBound = mDragHandleClosedBelow;
+ mChallengeBottomBound = res.getDimensionPixelSize(R.dimen.kg_widget_pager_bottom_padding);
setWillNotDraw(false);
}
@@ -293,21 +304,43 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
mHandleAnimation.start();
}
- void animateFrame(boolean visible, boolean full) {
+ void animateFrame(final boolean visible, final boolean full) {
if (mFrameDrawable == null) return;
- if (mFrameAnimation != null) {
+ final float targetAlpha = visible ? (full ? 1.f : 0.5f) : 0.f;
+ if (mFrameAnimation != null && targetAlpha != mFrameAnimationTarget) {
mFrameAnimation.cancel();
- mFrameAnimation = null;
+ mFrameAnimationTarget = Float.MIN_VALUE;
}
- final float targetAlpha = visible ? (full ? 1.f : 0.5f) : 0.f;
- if (targetAlpha == mFrameAlpha) {
+ if (targetAlpha == mFrameAlpha || targetAlpha == mFrameAnimationTarget) {
return;
}
+ mFrameAnimationTarget = targetAlpha;
mFrameAnimation = ObjectAnimator.ofFloat(this, FRAME_ALPHA, targetAlpha);
mFrameAnimation.setInterpolator(sHandleFadeInterpolator);
mFrameAnimation.setDuration(HANDLE_ANIMATE_DURATION);
+ mFrameAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mFrameAnimationTarget = Float.MIN_VALUE;
+
+ if (!visible && full && mChallengeView != null) {
+ // Mess with padding/margin to remove insets on the bouncer frame.
+ mChallengeView.setPadding(0, 0, 0, 0);
+ LayoutParams lp = (LayoutParams) mChallengeView.getLayoutParams();
+ lp.leftMargin = lp.rightMargin = getChallengeMargin(true);
+ mChallengeView.setLayoutParams(lp);
+ }
+ mFrameAnimation = null;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mFrameAnimationTarget = Float.MIN_VALUE;
+ mFrameAnimation = null;
+ }
+ });
mFrameAnimation.start();
}
@@ -370,7 +403,9 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
mScrollState = state;
animateHandle(state == SCROLL_STATE_IDLE && !mChallengeShowing);
- animateFrame(false , false);
+ if (!mIsBouncing) {
+ animateFrame(false, false);
+ }
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(state);
}
@@ -380,6 +415,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
void completeChallengeScroll() {
setChallengeShowing(mChallengeOffset != 0);
setScrollState(SCROLL_STATE_IDLE);
+ mChallengeView.setLayerType(LAYER_TYPE_NONE, null);
}
void setScrimView(View scrim) {
@@ -461,7 +497,22 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
if (mScrimView != null) {
mScrimView.setVisibility(VISIBLE);
}
+
+ // Mess with padding/margin to inset the bouncer frame.
+ // We have more space available to us otherwise.
+ if (mChallengeView != null) {
+ if (mFrameDrawable == null || !mFrameDrawable.getPadding(mTempRect)) {
+ mTempRect.set(0, 0, 0, 0);
+ }
+ mChallengeView.setPadding(mTempRect.left, mTempRect.top, mTempRect.right,
+ mTempRect.bottom);
+ final LayoutParams lp = (LayoutParams) mChallengeView.getLayoutParams();
+ lp.leftMargin = lp.rightMargin = getChallengeMargin(false);
+ mChallengeView.setLayoutParams(lp);
+ }
+
animateFrame(true, true);
+
if (mBouncerListener != null) {
mBouncerListener.onBouncerStateChanged(true);
}
@@ -470,17 +521,26 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
@Override
public void hideBouncer() {
if (!mIsBouncing) return;
- setChallengeShowing(false);
+ showChallenge(false);
mIsBouncing = false;
if (mScrimView != null) {
mScrimView.setVisibility(GONE);
}
- animateFrame(false, false);
+ animateFrame(false, true);
if (mBouncerListener != null) {
mBouncerListener.onBouncerStateChanged(false);
}
}
+ private int getChallengeMargin(boolean expanded) {
+ return expanded && mHasGlowpad ? 0 : mDragHandleEdgeSlop;
+ }
+
+ private float getChallengeAlpha() {
+ float x = mChallengeOffset - 1;
+ return x * x * x + 1.f;
+ }
+
@Override
public void requestDisallowInterceptTouchEvent(boolean allowIntercept) {
// We'll intercept whoever we feel like! ...as long as it isn't a challenge view.
@@ -495,8 +555,6 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
}
mVelocityTracker.addMovement(ev);
- //Log.v(TAG, "onIntercept: " + ev);
-
final int action = ev.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
@@ -518,13 +576,15 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
if (!mIsBouncing &&
(isInDragHandle(x, y) || crossedDragHandle(x, y, mGestureStartY) ||
- (isInChallengeView(x, y) && mScrollState == SCROLL_STATE_SETTLING)) &&
+ (isInChallengeView(x, y) &&
+ (mScrollState == SCROLL_STATE_SETTLING || !mChallengeShowing))) &&
mActivePointerId == INVALID_POINTER) {
mActivePointerId = ev.getPointerId(i);
mGestureStartX = x;
mGestureStartY = y;
mGestureStartChallengeBottom = getChallengeBottom();
mDragging = true;
+ mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
} else if (isInChallengeView(x, y)) {
mBlockDrag = true;
}
@@ -601,6 +661,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
mActivePointerId = ev.getPointerId(i);
mGestureStartChallengeBottom = getChallengeBottom();
mDragging = true;
+ mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
break;
}
}
@@ -631,6 +692,52 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
}
/**
+ * The lifecycle of touch events is subtle and it's very easy to do something
+ * that will cause bugs that will be nasty to track when overriding this method.
+ * Normally one should always override onInterceptTouchEvent instead.
+ *
+ * To put it another way, don't try this at home.
+ */
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ final int action = ev.getActionMasked();
+ boolean handled = false;
+ if (action == MotionEvent.ACTION_DOWN) {
+ // Defensive programming: if we didn't get the UP or CANCEL, reset anyway.
+ mEdgeCaptured = false;
+ }
+ if (mWidgetsView != null && !mIsBouncing && (mEdgeCaptured || isEdgeSwipeBeginEvent(ev))) {
+ // Normally we would need to do a lot of extra stuff here.
+ // We can only get away with this because we haven't padded in
+ // the widget pager or otherwise transformed it during layout.
+ // We also don't support things like splitting MotionEvents.
+
+ // We set handled to captured even if dispatch is returning false here so that
+ // we don't send a different view a busted or incomplete event stream.
+ handled = mEdgeCaptured |= mWidgetsView.dispatchTouchEvent(ev);
+ }
+
+ if (!handled && !mEdgeCaptured) {
+ handled = super.dispatchTouchEvent(ev);
+ }
+
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ mEdgeCaptured = false;
+ }
+
+ return handled;
+ }
+
+ private boolean isEdgeSwipeBeginEvent(MotionEvent ev) {
+ if (ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
+ return false;
+ }
+
+ final float x = ev.getX();
+ return x < mDragHandleEdgeSlop || x >= getWidth() - mDragHandleEdgeSlop;
+ }
+
+ /**
* We only want to add additional vertical space to the drag handle when the panel is fully
* closed.
*/
@@ -699,8 +806,16 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
}
// We're going to play silly games with the frame's background drawable later.
mFrameDrawable = mChallengeView.getBackground();
+
+ if (!mHasLayout) {
+ // Set up the margin correctly based on our content for the first run.
+ mHasGlowpad = child.findViewById(R.id.keyguard_selector_view) != null;
+ lp.leftMargin = lp.rightMargin = getChallengeMargin(true);
+ }
} else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
setScrimView(child);
+ } else if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) {
+ mWidgetsView = child;
}
if (child.getVisibility() == GONE) continue;
@@ -752,7 +867,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
// we never want less than the handle size showing at the bottom.
final int bottom = layoutBottom + (int) ((childHeight - mChallengeBottomBound)
* (1 - mChallengeOffset));
- child.setAlpha(mChallengeOffset / 2 + 0.5f);
+ child.setAlpha(getChallengeAlpha());
child.layout(left, bottom - childHeight, left + childWidth, bottom);
} else {
// Non-challenge views lay out from the upper left, layered.
@@ -830,7 +945,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
}
if (mDragIconDrawable != null) {
- final int closedTop = getLayoutBottom() - mChallengeBottomBound;
+ final int closedTop = getLayoutBottom() - mDragHandleClosedBelow;
final int iconWidth = mDragIconDrawable.getIntrinsicWidth();
final int iconHeight = mDragIconDrawable.getIntrinsicHeight();
final int iconLeft = (challengeLeft + challengeRight - iconWidth) / 2;
@@ -888,7 +1003,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
mChallengeView.layout(mChallengeView.getLeft(),
bottom - mChallengeView.getHeight(), mChallengeView.getRight(), bottom);
- mChallengeView.setAlpha(offset / 2 + 0.5f);
+ mChallengeView.setAlpha(getChallengeAlpha());
if (mScrollListener != null) {
mScrollListener.onScrollPositionChanged(offset, mChallengeView.getTop());
}
@@ -980,6 +1095,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
public static final int CHILD_TYPE_NONE = 0;
public static final int CHILD_TYPE_CHALLENGE = 2;
public static final int CHILD_TYPE_SCRIM = 4;
+ public static final int CHILD_TYPE_WIDGETS = 5;
public LayoutParams() {
this(MATCH_PARENT, WRAP_CONTENT);
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
index 6ff33d7..69ccbc7 100755
--- a/services/java/com/android/server/BluetoothManagerService.java
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -53,6 +53,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED";
private static final String EXTRA_ACTION="action";
+ private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid";
private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
@@ -174,7 +175,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
//Enable
if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
enableHelper();
- } else if (!isNameAndAddressSet()) {
+ }
+
+ if (!isNameAndAddressSet()) {
//Sync the Bluetooth name and address from the Bluetooth Adapter
if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address...");
getNameAndAddress();
@@ -222,11 +225,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
*/
private void loadStoredNameAndAddress() {
if (DBG) Log.d(TAG, "Loading stored name and address");
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_address_validation) &&
+ Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) {
+ // if the valid flag is not set, don't load the address and name
+ if (DBG) Log.d(TAG, "invalid bluetooth name and address stored");
+ return;
+ }
mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
- if (mName == null || mAddress == null) {
- if (DBG) Log.d(TAG, "Name or address not cached...");
- }
+ if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
}
/**
@@ -249,6 +257,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
if (DBG) Log.d(TAG,"Stored Bluetoothaddress: " +
Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS));
}
+
+ if ((name != null) && (address != null)) {
+ Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1);
+ }
}
public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
@@ -560,8 +572,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
break;
}
case MESSAGE_SAVE_NAME_AND_ADDRESS: {
+ boolean unbind = false;
if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS");
synchronized(mConnection) {
+ if (!mEnable && mBluetooth != null) {
+ try {
+ mBluetooth.enable();
+ } catch (RemoteException e) {
+ Log.e(TAG,"Unable to call enable()",e);
+ }
+ }
+ }
+ if (mBluetooth != null) waitForOnOff(true, false);
+ synchronized(mConnection) {
if (mBluetooth != null) {
String name = null;
String address = null;
@@ -575,7 +598,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
if (name != null && address != null) {
storeNameAndAddress(name,address);
if (mConnection.isGetNameAddressOnly()) {
- unbindAndFinish();
+ unbind = true;
}
} else {
if (msg.arg1 < MAX_SAVE_RETRIES) {
@@ -586,10 +609,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} else {
Log.w(TAG,"Maximum name/address remote retrieval retry exceeded");
if (mConnection.isGetNameAddressOnly()) {
- unbindAndFinish();
+ unbind = true;
}
}
}
+ if (!mEnable) {
+ try {
+ mBluetooth.disable();
+ } catch (RemoteException e) {
+ Log.e(TAG,"Unable to call disable()",e);
+ }
+ }
} else {
// rebind service by Request GET NAME AND ADDRESS
// if service is unbinded by disable or
@@ -598,6 +628,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mHandler.sendMessage(getMsg);
}
}
+ if (!mEnable && mBluetooth != null) waitForOnOff(false, true);
+ if (unbind) {
+ unbindAndFinish();
+ }
break;
}
case MESSAGE_ENABLE:
@@ -677,14 +711,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
//Inform BluetoothAdapter instances that service is up
sendBluetoothServiceUpCallback();
- //Check if name and address is loaded if not get it first.
- if (!isNameAndAddressSet()) {
- try {
- storeNameAndAddress(mBluetooth.getName(),
- mBluetooth.getAddress());
- } catch (RemoteException e) {Log.e(TAG, "", e);};
- }
-
//Do enable request
try {
if (mQuietEnable == false) {
@@ -873,14 +899,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
sendBluetoothServiceUpCallback();
}
- //Check if name and address is loaded if not get it first.
- if (!isNameAndAddressSet()) {
- try {
- if (DBG) Log.d(TAG,"Getting and storing Bluetooth name and address prior to enable.");
- storeNameAndAddress(mBluetooth.getName(),mBluetooth.getAddress());
- } catch (RemoteException e) {Log.e(TAG, "", e);};
- }
-
//Enable bluetooth
try {
if (!mQuietEnable) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 3532c0c..7958f9a 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2773,7 +2773,7 @@ public class WindowManagerService extends IWindowManager.Stub
// TODO: Remove once b/7094175 is fixed
|| ((String)win.mAttrs.getTitle()).contains("Keyguard")
) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
- + " " + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
+ + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
@@ -3003,6 +3003,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+ if (DEBUG_LAYOUT) {
+ Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
+ }
}
if (configChanged) {
@@ -8379,7 +8383,8 @@ public class WindowManagerService extends IWindowManager.Stub
// windows, since that means "perform layout as normal,
// just don't display").
if (!gone || !win.mHaveFrame || win.mLayoutNeeded
- || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
+ || ((win.mAttrs.type == TYPE_KEYGUARD || win.mAttrs.type == TYPE_WALLPAPER) &&
+ win.isConfigChanged())
|| win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
if (!win.mLayoutAttached) {
if (initial) {
@@ -9301,6 +9306,8 @@ public class WindowManagerService extends IWindowManager.Stub
Log.wtf(TAG, "Unhandled exception in Window Manager", e);
} finally {
Surface.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
}
final WindowList defaultWindows = defaultDisplay.getWindowList();