Merge "Ensure wallpaper hint is at least the display's max size." into klp-dev
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 2ab5a91..ed9264a 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -33,7 +33,6 @@
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.TypedValue;
import android.util.Xml;
import android.view.LayoutInflater;
@@ -125,8 +124,6 @@
PreferenceManager.OnPreferenceTreeClickListener,
PreferenceFragment.OnPreferenceStartFragmentCallback {
- private static final String TAG = "PreferenceActivity";
-
// Constants for state save/restore
private static final String HEADERS_TAG = ":android:headers";
private static final String CUR_HEADER_TAG = ":android:cur_header";
@@ -576,12 +573,14 @@
// Single pane, showing just a prefs fragment.
findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE);
mPrefsContainer.setVisibility(View.VISIBLE);
+ CharSequence initialTitleStr = null;
+ CharSequence initialShortTitleStr = null;
if (initialTitle != 0) {
- CharSequence initialTitleStr = getText(initialTitle);
- CharSequence initialShortTitleStr = initialShortTitle != 0
+ initialTitleStr = getText(initialTitle);
+ initialShortTitleStr = initialShortTitle != 0
? getText(initialShortTitle) : null;
- showBreadCrumbs(initialTitleStr, initialShortTitleStr);
}
+ showBreadCrumbs(initialTitleStr, initialShortTitleStr);
} else if (mHeaders.size() > 0) {
setListAdapter(new HeaderAdapter(this, mHeaders));
if (!mSinglePane) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e2d98ed..aa2b0d4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3102,6 +3102,8 @@
*/
private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
+ private boolean mUseBackgroundPadding = false;
+
/**
* @hide
*/
@@ -5900,6 +5902,8 @@
sThreadLocal.set(localInsets);
}
boolean res = computeFitSystemWindows(insets, localInsets);
+ mUserPaddingLeftInitial = localInsets.left;
+ mUserPaddingRightInitial = localInsets.right;
internalSetPadding(localInsets.left, localInsets.top,
localInsets.right, localInsets.bottom);
return res;
@@ -12133,12 +12137,14 @@
if (!isTextAlignmentResolved()) {
resolveTextAlignment();
}
- if (!isPaddingResolved()) {
- resolvePadding();
- }
+ // Should resolve Drawables before Padding because we need the layout direction of the
+ // Drawable to correctly resolve Padding.
if (!isDrawablesResolved()) {
resolveDrawables();
}
+ if (!isPaddingResolved()) {
+ resolvePadding();
+ }
onRtlPropertiesChanged(getLayoutDirection());
return true;
}
@@ -12341,6 +12347,16 @@
// If start / end padding are defined, they will be resolved (hence overriding) to
// left / right or right / left depending on the resolved layout direction.
// If start / end padding are not defined, use the left / right ones.
+ if (mBackground != null && mUseBackgroundPadding) {
+ Rect padding = sThreadLocal.get();
+ if (padding == null) {
+ padding = new Rect();
+ sThreadLocal.set(padding);
+ }
+ mBackground.getPadding(padding);
+ mUserPaddingLeftInitial = padding.left;
+ mUserPaddingRightInitial = padding.right;
+ }
switch (resolvedLayoutDirection) {
case LAYOUT_DIRECTION_RTL:
if (mUserPaddingStart != UNDEFINED_PADDING) {
@@ -15336,6 +15352,9 @@
mUserPaddingRightInitial = padding.right;
internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
}
+ mUseBackgroundPadding = true;
+ } else {
+ mUseBackgroundPadding = false;
}
// Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
@@ -15361,6 +15380,8 @@
/* Remove the background */
mBackground = null;
+ mUseBackgroundPadding = false;
+
if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
/*
* This view ONLY drew the background before and we're removing
@@ -15432,6 +15453,8 @@
mUserPaddingLeftInitial = left;
mUserPaddingRightInitial = right;
+ mUseBackgroundPadding = false;
+
internalSetPadding(left, top, right, bottom);
}
@@ -15518,6 +15541,8 @@
mUserPaddingStart = start;
mUserPaddingEnd = end;
+ mUseBackgroundPadding = false;
+
switch(getLayoutDirection()) {
case LAYOUT_DIRECTION_RTL:
mUserPaddingLeftInitial = end;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cb930d6..7a9809f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -56,6 +56,7 @@
import android.text.SpanWatcher;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.StaticLayout;
@@ -3494,19 +3495,7 @@
ss.selEnd = end;
if (mText instanceof Spanned) {
- /*
- * Calling setText() strips off any ChangeWatchers;
- * strip them now to avoid leaking references.
- * But do it to a copy so that if there are any
- * further changes to the text of this view, it
- * won't get into an inconsistent state.
- */
-
- Spannable sp = new SpannableString(mText);
-
- for (ChangeWatcher cw : sp.getSpans(0, sp.length(), ChangeWatcher.class)) {
- sp.removeSpan(cw);
- }
+ Spannable sp = new SpannableStringBuilder(mText);
if (mEditor != null) {
removeMisspelledSpans(sp);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 73d34c3..c44afae 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -301,6 +301,8 @@
count++;
} catch (ClassNotFoundException e) {
Log.w(TAG, "Class not found for preloading: " + line);
+ } catch (UnsatisfiedLinkError e) {
+ Log.w(TAG, "Problem preloading " + line + ": " + e);
} catch (Throwable t) {
Log.e(TAG, "Error preloading " + line + ".", t);
if (t instanceof Error) {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 44e7ec1..4654178 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -721,7 +721,8 @@
if (subMenu == null) return false;
mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
- return false;
+ final MenuPresenter.Callback cb = getCallback();
+ return cb != null ? cb.onOpenSubMenu(subMenu) : false;
}
@Override
@@ -729,6 +730,10 @@
if (menu instanceof SubMenuBuilder) {
((SubMenuBuilder) menu).getRootMenu().close(false);
}
+ final MenuPresenter.Callback cb = getCallback();
+ if (cb != null) {
+ cb.onCloseMenu(menu, allMenusAreClosing);
+ }
}
}
diff --git a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
index db0d6dd..92e9ea6 100644
--- a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
@@ -144,6 +144,10 @@
mCallback = cb;
}
+ public Callback getCallback() {
+ return mCallback;
+ }
+
/**
* Create a new item view that can be re-bound to other item data later.
*
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index b5d74e8..5f9d8f2 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -566,7 +566,11 @@
mUpGoerFive.setEnabled(enable);
mUpGoerFive.setFocusable(enable);
// Make sure the home button has an accurate content description for accessibility.
- if (!enable) {
+ updateHomeAccessibility(enable);
+ }
+
+ private void updateHomeAccessibility(boolean homeEnabled) {
+ if (!homeEnabled) {
mUpGoerFive.setContentDescription(null);
mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
} else {
@@ -677,19 +681,7 @@
}
// Make sure the home button has an accurate content description for accessibility.
- if (!mHomeLayout.isEnabled()) {
- mHomeLayout.setContentDescription(null);
- mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
- } else {
- mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
- if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
- mHomeLayout.setContentDescription(mContext.getResources().getText(
- R.string.action_bar_up_description));
- } else {
- mHomeLayout.setContentDescription(mContext.getResources().getText(
- R.string.action_bar_home_description));
- }
- }
+ updateHomeAccessibility(!mUpGoerFive.isEnabled());
}
public void setIcon(Drawable icon) {
diff --git a/docs/html/about/versions/kitkat.jd b/docs/html/about/versions/kitkat.jd
index 6c6cb6c..92ebf65 100644
--- a/docs/html/about/versions/kitkat.jd
+++ b/docs/html/about/versions/kitkat.jd
@@ -55,7 +55,7 @@
<div id="44-android-44" class="version-section">
<div style="padding:0px 0px 0px 60px;margin-top:-3px;float:right;">
- <img src="{@docRoot}images/kk-android-44.png" alt="Android 4.4 on phone and tablet" width="380">
+ <img src="{@docRoot}design/media/index_landing_page.png" alt="Android 4.4 on phone and tablet" width="380">
</div>
<div class="landing-docs" style="float:right;clear:both;margin:22px 0 2em 3em;">
@@ -143,7 +143,8 @@
lets you tune your app's behavior to match the device's memory configuration.
You can modify or disable large-memory features as needed, depending on the
use-cases you want to support on entry-level devices. Learn more about
- optimizing your apps for low-memory devices <a href="">here</a>.
+ optimizing your apps for low-memory devices <a
+ href="{@docRoot}training/articles/memory.html">here</a>.
</p>
<p>
@@ -612,18 +613,20 @@
Now it's easy to create high-quality video of your app, directly from your
Android device. <span style="white-space:nowrap;">Android 4.4</span> adds
support for screen recording and provides a <strong>screen recording
- utility</strong> that lets you capture video as you use the device and store
- it as an MP4 file. It's a great new way to create walkthroughs and tutorials
- for your app, testing materials, marketing videos, and much more.
+ utility</strong> that lets you start and stop recording on a device that's
+ connected to your Android SDK environment over USB. It's a great new way to
+ create walkthroughs and tutorials for your app, testing materials, marketing
+ videos, and more.
</p>
<p>
- You can record at any device-supported resolution and bitrate you want, and
- the output retains the aspect ratio of the display. By default, the utility
- selects a resolution equal or close to the device's display resolution in the
- current orientation. When you are done recording, you can share the video
- directly from your device or pull the MP4 file to your host computer for
- post-production.
+ With the screen recording utility, you can capture video of your device screen
+ contents and store the video as an MP4 file on the device. You can record at any
+ device-supported resolution and bitrate you want, and the output retains the
+ aspect ratio of the display. By default, the utility selects a resolution
+ equal or close to the device's display resolution in the current orientation.
+ When you are done recording, you can share the video directly from your
+ device or pull the MP4 file to your host computer for post-production.
</p>
<p>
@@ -827,9 +830,7 @@
<p>
<span style="white-space:nowrap;">Android 4.4</span> upgrades its
- SurfaceFlinger from OpenGL ES 1.0 to OpenGL ES 2.0. This boosts performance
- by using multi-texturing, and it improves color calibration and supports more
- advanced special effects.
+ SurfaceFlinger from OpenGL ES 1.0 to OpenGL ES 2.0.
</p>
<h4 id="44-composer">New Hardware Composer support for virtual displays</h4>
diff --git a/docs/html/images/kk-saf2-n5.jpg b/docs/html/images/kk-saf2-n5.jpg
index c96d5d4..1c54a95 100644
--- a/docs/html/images/kk-saf2-n5.jpg
+++ b/docs/html/images/kk-saf2-n5.jpg
Binary files differ
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index e350e8d..60e2376 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -23,6 +23,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.SystemClock;
+import android.util.LayoutDirection;
import android.util.SparseArray;
/**
@@ -59,6 +60,8 @@
private long mExitAnimationEnd;
private Drawable mLastDrawable;
+ private Insets mInsets;
+
// overrides from Drawable
@Override
@@ -78,18 +81,30 @@
| mDrawableContainerState.mChildrenChangingConfigurations;
}
+ private boolean needsMirroring() {
+ return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
+ }
+
@Override
public boolean getPadding(Rect padding) {
final Rect r = mDrawableContainerState.getConstantPadding();
+ boolean result = true;
if (r != null) {
padding.set(r);
- return true;
- }
- if (mCurrDrawable != null) {
- return mCurrDrawable.getPadding(padding);
} else {
- return super.getPadding(padding);
+ if (mCurrDrawable != null) {
+ result = mCurrDrawable.getPadding(padding);
+ } else {
+ result = super.getPadding(padding);
+ }
}
+ if (needsMirroring()) {
+ final int left = padding.left;
+ final int right = padding.right;
+ padding.left = right;
+ padding.right = left;
+ }
+ return result;
}
/**
@@ -97,7 +112,7 @@
*/
@Override
public Insets getOpticalInsets() {
- return (mCurrDrawable == null) ? Insets.NONE : mCurrDrawable.getOpticalInsets();
+ return mInsets;
}
@Override
@@ -334,6 +349,7 @@
mCurrDrawable = d;
mCurIndex = idx;
if (d != null) {
+ mInsets = d.getOpticalInsets();
d.mutate();
if (mDrawableContainerState.mEnterFadeDuration > 0) {
mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration;
@@ -348,9 +364,12 @@
d.setBounds(getBounds());
d.setLayoutDirection(getLayoutDirection());
d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
+ } else {
+ mInsets = Insets.NONE;
}
} else {
mCurrDrawable = null;
+ mInsets = Insets.NONE;
mCurIndex = -1;
}
diff --git a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
index 8be15cb..b4847f0 100644
--- a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
+++ b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
@@ -32,12 +32,10 @@
android:id="@+id/carrier_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@dimen/kg_status_line_font_size"
- android:textColor="?android:attr/textColorSecondary"
- android:textAllCaps="@bool/kg_use_all_caps" />
+ android:textColor="?android:attr/textColorSecondary" />
<LinearLayout
android:layout_width="match_parent"
diff --git a/packages/Keyguard/src/com/android/keyguard/CarrierText.java b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
index c33f174..88558cd 100644
--- a/packages/Keyguard/src/com/android/keyguard/CarrierText.java
+++ b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
@@ -17,14 +17,18 @@
package com.android.keyguard;
import android.content.Context;
+import android.text.method.SingleLineTransformationMethod;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.TextView;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.widget.LockPatternUtils;
+import java.util.Locale;
+
public class CarrierText extends TextView {
private static CharSequence mSeparator;
@@ -77,6 +81,8 @@
public CarrierText(Context context, AttributeSet attrs) {
super(context, attrs);
mLockPatternUtils = new LockPatternUtils(mContext);
+ boolean useAllCaps = mContext.getResources().getBoolean(R.bool.kg_use_all_caps);
+ setTransformationMethod(new CarrierTextTransformationMethod(mContext, useAllCaps));
}
protected void updateCarrierText(State simState, CharSequence plmn, CharSequence spn) {
@@ -258,4 +264,25 @@
return mContext.getText(carrierHelpTextId);
}
+
+ private class CarrierTextTransformationMethod extends SingleLineTransformationMethod {
+ private final Locale mLocale;
+ private final boolean mAllCaps;
+
+ public CarrierTextTransformationMethod(Context context, boolean allCaps) {
+ mLocale = context.getResources().getConfiguration().locale;
+ mAllCaps = allCaps;
+ }
+
+ @Override
+ public CharSequence getTransformation(CharSequence source, View view) {
+ source = super.getTransformation(source, view);
+
+ if (mAllCaps && source != null) {
+ source = source.toString().toUpperCase(mLocale);
+ }
+
+ return source;
+ }
+ }
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index e39622a..9accbb4 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -46,9 +46,10 @@
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
private static final String LOG_TAG = "KeyguardSimPinView";
private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+ public static final String TAG = "KeyguardSimPinView";
private ProgressDialog mSimUnlockProgressDialog = null;
- private volatile boolean mSimCheckInProgress;
+ private CheckSimPin mCheckSimPinThread;
private AlertDialog mRemainingAttemptsDialog;
@@ -169,14 +170,17 @@
@Override
public void run() {
try {
+ Log.v(TAG, "call supplyPinReportResult()");
final int[] result = ITelephony.Stub.asInterface(ServiceManager
.checkService("phone")).supplyPinReportResult(mPin);
+ Log.v(TAG, "supplyPinReportResult returned: " + result[0] + " " + result[1]);
post(new Runnable() {
public void run() {
onSimCheckResponse(result[0], result[1]);
}
});
} catch (RemoteException e) {
+ Log.e(TAG, "RemoteException for supplyPinReportResult:", e);
post(new Runnable() {
public void run() {
onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
@@ -229,9 +233,8 @@
getSimUnlockProgressDialog().show();
- if (!mSimCheckInProgress) {
- mSimCheckInProgress = true; // there should be only one
- new CheckSimPin(mPasswordEntry.getText().toString()) {
+ if (mCheckSimPinThread == null) {
+ mCheckSimPinThread = new CheckSimPin(mPasswordEntry.getText().toString()) {
void onSimCheckResponse(final int result, final int attemptsRemaining) {
post(new Runnable() {
public void run() {
@@ -263,11 +266,12 @@
mPasswordEntry.setText("");
}
mCallback.userActivity(0);
- mSimCheckInProgress = false;
+ mCheckSimPinThread = null;
}
});
}
- }.start();
+ };
+ mCheckSimPinThread.start();
}
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index 31518a1..6e9e83e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -45,9 +45,10 @@
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
private static final String LOG_TAG = "KeyguardSimPukView";
private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+ public static final String TAG = "KeyguardSimPukView";
private ProgressDialog mSimUnlockProgressDialog = null;
- private volatile boolean mCheckInProgress;
+ private CheckSimPuk mCheckSimPukThread;
private String mPukText;
private String mPinText;
private StateMachine mStateMachine = new StateMachine();
@@ -220,15 +221,17 @@
@Override
public void run() {
try {
+ Log.v(TAG, "call supplyPukReportResult()");
final int[] result = ITelephony.Stub.asInterface(ServiceManager
.checkService("phone")).supplyPukReportResult(mPuk, mPin);
-
+ Log.v(TAG, "supplyPukReportResult returned: " + result[0] + " " + result[1]);
post(new Runnable() {
public void run() {
onSimLockChangedResponse(result[0], result[1]);
}
});
} catch (RemoteException e) {
+ Log.e(TAG, "RemoteException for supplyPukReportResult:", e);
post(new Runnable() {
public void run() {
onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
@@ -295,9 +298,8 @@
private void updateSim() {
getSimUnlockProgressDialog().show();
- if (!mCheckInProgress) {
- mCheckInProgress = true;
- new CheckSimPuk(mPukText, mPinText) {
+ if (mCheckSimPukThread == null) {
+ mCheckSimPukThread = new CheckSimPuk(mPukText, mPinText) {
void onSimLockChangedResponse(final int result, final int attemptsRemaining) {
post(new Runnable() {
public void run() {
@@ -326,11 +328,12 @@
+ " attemptsRemaining=" + attemptsRemaining);
mStateMachine.reset();
}
- mCheckInProgress = false;
+ mCheckSimPukThread = null;
}
});
}
- }.start();
+ };
+ mCheckSimPukThread.start();
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
index 7a9a1c8..3d515ce 100644
--- a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
+++ b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
@@ -1003,6 +1003,16 @@
}
}
+ @Override
+ protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+ // Focus security fileds before widgets.
+ if (mChallengeView != null &&
+ mChallengeView.requestFocus(direction, previouslyFocusedRect)) {
+ return true;
+ }
+ return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
+ }
+
public void computeScroll() {
super.computeScroll();
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index f2e768a..d2613d0f 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -93,6 +93,12 @@
<!-- Title of the action bar button to got to add a printer. [CHAR LIMIT=25] -->
<string name="print_add_printer">Add printer</string>
+ <!-- Title of the menu item to select a printer. [CHAR LIMIT=25] -->
+ <string name="print_select_printer">Select printer</string>
+
+ <!-- Title of the menu item to forget a printer. [CHAR LIMIT=25] -->
+ <string name="print_forget_printer">Forget printer</string>
+
<!-- Utterance to announce a change in the number of matches during a search. This is spoken to a blind user. [CHAR LIMIT=none] -->
<plurals name="print_search_result_count_utterance">
<item quantity="one"><xliff:g id="count" example="1">%1$s</xliff:g> printer found</item>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
index 0601467..9831839 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
@@ -79,6 +79,8 @@
private PrinterId mTrackedPrinter;
+ private boolean mPrintersUpdatedBefore;
+
public FusedPrintersProvider(Context context) {
super(context);
mPersistenceManager = new PersistenceManager(context);
@@ -88,13 +90,14 @@
mPersistenceManager.addPrinterAndWritePrinterHistory(printer);
}
- private void computeAndDeliverResult(Map<PrinterId, PrinterInfo> discoveredPrinters) {
+ private void computeAndDeliverResult(ArrayMap<PrinterId, PrinterInfo> discoveredPrinters,
+ ArrayMap<PrinterId, PrinterInfo> favoritePrinters) {
List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
// Add the updated favorite printers.
- final int favoritePrinterCount = mFavoritePrinters.size();
+ final int favoritePrinterCount = favoritePrinters.size();
for (int i = 0; i < favoritePrinterCount; i++) {
- PrinterInfo favoritePrinter = mFavoritePrinters.get(i);
+ PrinterInfo favoritePrinter = favoritePrinters.valueAt(i);
PrinterInfo updatedPrinter = discoveredPrinters.remove(
favoritePrinter.getId());
if (updatedPrinter != null) {
@@ -123,8 +126,11 @@
mPrinters.addAll(printers);
if (isStarted()) {
- // Deliver the printers.
+ // If stated deliver the new printers.
deliverResult(printers);
+ } else {
+ // Otherwise, take a note for the change.
+ onContentChanged();
}
}
@@ -165,6 +171,8 @@
.getSystemService(Context.PRINT_SERVICE);
mDiscoverySession = printManager.createPrinterDiscoverySession();
mPersistenceManager.readPrinterHistory();
+ } else if (mPersistenceManager.isHistoryChanged()) {
+ mPersistenceManager.readPrinterHistory();
}
if (mPersistenceManager.isReadHistoryCompleted()
&& !mDiscoverySession.isPrinterDiscoveryStarted()) {
@@ -176,7 +184,7 @@
+ mDiscoverySession.getPrinters().size()
+ " " + FusedPrintersProvider.this.hashCode());
}
- updatePrinters(mDiscoverySession.getPrinters());
+ updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters);
}
});
final int favoriteCount = mFavoritePrinters.size();
@@ -187,15 +195,19 @@
mDiscoverySession.startPrinterDisovery(printerIds);
List<PrinterInfo> printers = mDiscoverySession.getPrinters();
if (!printers.isEmpty()) {
- updatePrinters(printers);
+ updatePrinters(printers, mFavoritePrinters);
}
}
}
- private void updatePrinters(List<PrinterInfo> printers) {
- if (mPrinters.equals(printers)) {
+ private void updatePrinters(List<PrinterInfo> printers, List<PrinterInfo> favoritePrinters) {
+ if (mPrintersUpdatedBefore && mPrinters.equals(printers)
+ && mFavoritePrinters.equals(favoritePrinters)) {
return;
}
+
+ mPrintersUpdatedBefore = true;
+
ArrayMap<PrinterId, PrinterInfo> printersMap =
new ArrayMap<PrinterId, PrinterInfo>();
final int printerCount = printers.size();
@@ -203,7 +215,16 @@
PrinterInfo printer = printers.get(i);
printersMap.put(printer.getId(), printer);
}
- computeAndDeliverResult(printersMap);
+
+ ArrayMap<PrinterId, PrinterInfo> favoritePrintersMap =
+ new ArrayMap<PrinterId, PrinterInfo>();
+ final int favoritePrinterCount = favoritePrinters.size();
+ for (int i = 0; i < favoritePrinterCount; i++) {
+ PrinterInfo favoritePrinter = favoritePrinters.get(i);
+ favoritePrintersMap.put(favoritePrinter.getId(), favoritePrinter);
+ }
+
+ computeAndDeliverResult(printersMap, favoritePrintersMap);
}
@Override
@@ -264,6 +285,42 @@
}
}
+ public boolean isFavoritePrinter(PrinterId printerId) {
+ final int printerCount = mFavoritePrinters.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo favoritePritner = mFavoritePrinters.get(i);
+ if (favoritePritner.getId().equals(printerId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void forgetFavoritePrinter(PrinterId printerId) {
+ List<PrinterInfo> newFavoritePrinters = null;
+
+ // Remove the printer from the favorites.
+ final int favoritePrinterCount = mFavoritePrinters.size();
+ for (int i = 0; i < favoritePrinterCount; i++) {
+ PrinterInfo favoritePrinter = mFavoritePrinters.get(i);
+ if (favoritePrinter.getId().equals(printerId)) {
+ newFavoritePrinters = new ArrayList<PrinterInfo>();
+ newFavoritePrinters.addAll(mPrinters);
+ newFavoritePrinters.remove(i);
+ break;
+ }
+ }
+
+ // If we removed a favorite printer, we have work to do.
+ if (newFavoritePrinters != null) {
+ // Remove the printer from history and persist the latter.
+ mPersistenceManager.removeHistoricalPrinterAndWritePrinterHistory(printerId);
+
+ // Recompute and deliver the printers.
+ updatePrinters(mDiscoverySession.getPrinters(), newFavoritePrinters);
+ }
+ }
+
private final class PersistenceManager {
private static final String PERSIST_FILE_NAME = "printer_history.xml";
@@ -281,13 +338,15 @@
private final AtomicFile mStatePersistFile;
- private List<PrinterInfo> mHistoricalPrinters;
+ private List<PrinterInfo> mHistoricalPrinters = new ArrayList<PrinterInfo>();
private boolean mReadHistoryCompleted;
private boolean mReadHistoryInProgress;
private ReadTask mReadTask;
+ private volatile long mLastReadHistoryTimestamp;
+
private PersistenceManager(Context context) {
mStatePersistFile = new AtomicFile(new File(context.getFilesDir(),
PERSIST_FILE_NAME));
@@ -327,6 +386,27 @@
new ArrayList<PrinterInfo>(mHistoricalPrinters));
}
+ @SuppressWarnings("unchecked")
+ public void removeHistoricalPrinterAndWritePrinterHistory(PrinterId printerId) {
+ boolean writeHistory = false;
+ final int printerCount = mHistoricalPrinters.size();
+ for (int i = printerCount - 1; i >= 0; i--) {
+ PrinterInfo historicalPrinter = mHistoricalPrinters.get(i);
+ if (historicalPrinter.getId().equals(printerId)) {
+ mHistoricalPrinters.remove(i);
+ writeHistory = true;
+ }
+ }
+ if (writeHistory) {
+ new WriteTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,
+ new ArrayList<PrinterInfo>(mHistoricalPrinters));
+ }
+ }
+
+ public boolean isHistoryChanged() {
+ return mLastReadHistoryTimestamp != mStatePersistFile.getBaseFile().lastModified();
+ }
+
private List<PrinterInfo> computeFavoritePrinters(List<PrinterInfo> printers) {
Map<PrinterId, PrinterRecord> recordMap =
new ArrayMap<PrinterId, PrinterRecord>();
@@ -423,11 +503,10 @@
mReadHistoryInProgress = false;
mReadHistoryCompleted = true;
- // Deliver the favorites.
- Map<PrinterId, PrinterInfo> discoveredPrinters = Collections.emptyMap();
- computeAndDeliverResult(discoveredPrinters);
+ // Deliver the printers.
+ updatePrinters(mDiscoverySession.getPrinters(), mHistoricalPrinters);
- // Start loading the available printers.
+ // Loading the available printers if needed.
loadInternal();
// We are done.
@@ -450,6 +529,8 @@
XmlPullParser parser = Xml.newPullParser();
parser.setInput(in, null);
parseState(parser, printers);
+ // Take a note which version of the history was read.
+ mLastReadHistoryTimestamp = mStatePersistFile.getBaseFile().lastModified();
return printers;
} catch (IllegalStateException ise) {
Slog.w(LOG_TAG, "Failed parsing ", ise);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 6d0ecd7..88403a3 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -937,6 +937,7 @@
mPrintJobId, mCurrentPrinter);
if (mCurrentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) {
+ mCapabilitiesTimeout.post();
updateUi();
return;
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index 609ae64..778fb4d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -544,7 +544,7 @@
final int printJobCount = mPrintJobs.size();
for (int i = 0; i < printJobCount; i++) {
PrintJobInfo printJob = mPrintJobs.get(i);
- if (isActiveState(printJob.getState())
+ if (isActiveState(printJob.getState()) && printJob.getPrinterId() != null
&& printJob.getPrinterId().getServiceName().equals(service)) {
return true;
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
index 204c152..fe5920c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
@@ -46,6 +46,8 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -54,6 +56,7 @@
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.AdapterView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Filter;
@@ -81,6 +84,8 @@
private static final String FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS =
"FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS";
+ private static final String EXTRA_PRINTER_ID = "EXTRA_PRINTER_ID";
+
private final ArrayList<PrintServiceInfo> mAddPrinterServices =
new ArrayList<PrintServiceInfo>();
@@ -127,6 +132,9 @@
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (!((DestinationAdapter) mListView.getAdapter()).isActionable(position)) {
+ return;
+ }
PrinterInfo printer = (PrinterInfo) mListView.getAdapter().getItem(position);
Activity activity = getActivity();
if (activity instanceof OnPrinterSelectedListener) {
@@ -138,6 +146,8 @@
}
});
+ registerForContextMenu(mListView);
+
return content;
}
@@ -185,6 +195,62 @@
}
@Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
+ if (view == mListView) {
+ final int position = ((AdapterContextMenuInfo) menuInfo).position;
+ PrinterInfo printer = (PrinterInfo) mListView.getAdapter().getItem(position);
+
+ menu.setHeaderTitle(printer.getName());
+
+ // Add the select menu item if applicable.
+ if (printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE) {
+ MenuItem selectItem = menu.add(Menu.NONE, R.string.print_select_printer,
+ Menu.NONE, R.string.print_select_printer);
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_PRINTER_ID, printer.getId());
+ selectItem.setIntent(intent);
+ }
+
+ // Add the forget menu item if applicable.
+ FusedPrintersProvider provider = (FusedPrintersProvider) (Loader<?>)
+ getLoaderManager().getLoader(LOADER_ID_PRINTERS_LOADER);
+ if (provider.isFavoritePrinter(printer.getId())) {
+ MenuItem forgetItem = menu.add(Menu.NONE, R.string.print_forget_printer,
+ Menu.NONE, R.string.print_forget_printer);
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_PRINTER_ID, printer.getId());
+ forgetItem.setIntent(intent);
+ }
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.string.print_select_printer: {
+ PrinterId printerId = (PrinterId) item.getIntent().getParcelableExtra(
+ EXTRA_PRINTER_ID);
+ Activity activity = getActivity();
+ if (activity instanceof OnPrinterSelectedListener) {
+ ((OnPrinterSelectedListener) activity).onPrinterSelected(printerId);
+ } else {
+ throw new IllegalStateException("the host activity must implement"
+ + " OnPrinterSelectedListener");
+ }
+ } return true;
+
+ case R.string.print_forget_printer: {
+ PrinterId printerId = (PrinterId) item.getIntent().getParcelableExtra(
+ EXTRA_PRINTER_ID);
+ FusedPrintersProvider provider = (FusedPrintersProvider) (Loader<?>)
+ getLoaderManager().getLoader(LOADER_ID_PRINTERS_LOADER);
+ provider.forgetFavoritePrinter(printerId);
+ } return true;
+ }
+ return false;
+ }
+
+ @Override
public void onResume() {
updateAddPrintersAdapter();
getActivity().invalidateOptionsMenu();
@@ -464,7 +530,7 @@
R.layout.printer_list_item, parent, false);
}
- convertView.setEnabled(isEnabled(position));
+ convertView.setEnabled(isActionable(position));
CharSequence title = null;
CharSequence subtitle = null;
@@ -506,8 +572,7 @@
return convertView;
}
- @Override
- public boolean isEnabled(int position) {
+ public boolean isActionable(int position) {
PrinterInfo printer = (PrinterInfo) getItem(position);
return printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index e77b420..4901823 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -113,7 +113,7 @@
handled = super.onTouchEvent(ev);
}
final int action = ev.getAction();
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
}
return handled;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 63e09db..a645c01 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -8269,7 +8269,7 @@
// 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.isConfigChanged()
|| win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
if (!win.mLayoutAttached) {
if (initial) {
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index ab429fd..e3a1aa6 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1957,6 +1957,27 @@
}
/**
+ * Process phone number for CDMA, converting plus code using the home network number format.
+ * This is used for outgoing SMS messages.
+ *
+ * @param dialStr the original dial string
+ * @return the converted dial string
+ * @hide for internal use
+ */
+ public static String cdmaCheckAndProcessPlusCodeForSms(String dialStr) {
+ if (!TextUtils.isEmpty(dialStr)) {
+ if (isReallyDialable(dialStr.charAt(0)) && isNonSeparator(dialStr)) {
+ String defaultIso = SystemProperties.get(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
+ if (!TextUtils.isEmpty(defaultIso)) {
+ int format = getFormatTypeFromCountryCode(defaultIso);
+ return cdmaCheckAndProcessPlusCodeByNumberFormat(dialStr, format, format);
+ }
+ }
+ }
+ return dialStr;
+ }
+
+ /**
* This function should be called from checkAndProcessPlusCode only
* And it is used for test purpose also.
*