Merge "Support preferred activities with zero or one scheme in the filter" into klp-dev
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 4fe2c4d..a38beec 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -334,6 +334,27 @@
/**
* <p>
+ * If set to 1, the HAL will always split result
+ * metadata for a single capture into multiple buffers,
+ * returned using multiple process_capture_result calls.
+ * </p>
+ * <p>
+ * Does not need to be listed in static
+ * metadata. Support for partial results will be reworked in
+ * future versions of camera service. This quirk will stop
+ * working at that point; DO NOT USE without careful
+ * consideration of future support.
+ * </p>
+ *
+ * <b>Optional</b> - This value may be null on some devices.
+ *
+ * @hide
+ */
+ public static final Key<Byte> QUIRKS_USE_PARTIAL_RESULT =
+ new Key<Byte>("android.quirks.usePartialResult", byte.class);
+
+ /**
+ * <p>
* How many output streams can be allocated at
* the same time for each type of stream
* </p>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 7095e4d..9e8d7d1 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -631,6 +631,36 @@
}
/**
+ * This method is called when some results from an image capture are
+ * available.
+ *
+ * <p>The result provided here will contain some subset of the fields of
+ * a full result. Multiple onCapturePartial calls may happen per
+ * capture; a given result field will only be present in one partial
+ * capture at most. The final onCaptureCompleted call will always
+ * contain all the fields, whether onCapturePartial was called or
+ * not.</p>
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param camera The CameraDevice sending the callback.
+ * @param request The request that was given to the CameraDevice
+ * @param result The partial output metadata from the capture, which
+ * includes a subset of the CaptureResult fields.
+ *
+ * @see #capture
+ * @see #captureBurst
+ * @see #setRepeatingRequest
+ * @see #setRepeatingBurst
+ *
+ * @hide
+ */
+ public void onCapturePartial(CameraDevice camera,
+ CaptureRequest request, CaptureResult result) {
+ // default empty implementation
+ }
+
+ /**
* This method is called when an image capture has completed and the
* result metadata is available.
*
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index dbd0457..535b963 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -591,6 +591,32 @@
/**
* <p>
+ * Whether a result given to the framework is the
+ * final one for the capture, or only a partial that contains a
+ * subset of the full set of dynamic metadata
+ * values.
+ * </p>
+ * <p>
+ * The entries in the result metadata buffers for a
+ * single capture may not overlap, except for this entry. The
+ * FINAL buffers must retain FIFO ordering relative to the
+ * requests that generate them, so the FINAL buffer for frame 3 must
+ * always be sent to the framework after the FINAL buffer for frame 2, and
+ * before the FINAL buffer for frame 4. PARTIAL buffers may be returned
+ * in any order relative to other frames, but all PARTIAL buffers for a given
+ * capture must arrive before the FINAL buffer for that capture. This entry may
+ * only be used by the HAL if quirks.usePartialResult is set to 1.
+ * </p>
+ *
+ * <b>Optional</b> - This value may be null on some devices.
+ *
+ * @hide
+ */
+ public static final Key<Boolean> QUIRKS_PARTIAL_RESULT =
+ new Key<Boolean>("android.quirks.partialResult", boolean.class);
+
+ /**
+ * <p>
* A frame counter set by the framework. This value monotonically
* increases with every new result (that is, each new result has a unique
* frameCount value).
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 814aa96..40586f0 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -577,6 +577,9 @@
}
final CaptureListenerHolder holder;
+ Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT);
+ boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial);
+
synchronized (mLock) {
// TODO: move this whole map into this class to make it more testable,
// exposing the methods necessary like subscribeToRequest, unsubscribe..
@@ -585,7 +588,7 @@
holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
// Clean up listener once we no longer expect to see it.
- if (holder != null && !holder.isRepeating()) {
+ if (holder != null && !holder.isRepeating() && !quirkIsPartialResult) {
CameraDevice.this.mCaptureListenerMap.remove(requestId);
}
@@ -595,7 +598,7 @@
// If we received a result for a repeating request and have
// prior repeating requests queued for deletion, remove those
// requests from mCaptureListenerMap.
- if (holder != null && holder.isRepeating()
+ if (holder != null && holder.isRepeating() && !quirkIsPartialResult
&& mRepeatingRequestIdDeletedList.size() > 0) {
Iterator<Integer> iter = mRepeatingRequestIdDeletedList.iterator();
while (iter.hasNext()) {
@@ -619,8 +622,25 @@
final CaptureRequest request = holder.getRequest();
final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId);
- holder.getHandler().post(
- new Runnable() {
+ Runnable resultDispatch = null;
+
+ // Either send a partial result or the final capture completed result
+ if (quirkIsPartialResult) {
+ // Partial result
+ resultDispatch = new Runnable() {
+ @Override
+ public void run() {
+ if (!CameraDevice.this.isClosed()){
+ holder.getListener().onCapturePartial(
+ CameraDevice.this,
+ request,
+ resultAsCapture);
+ }
+ }
+ };
+ } else {
+ // Final capture result
+ resultDispatch = new Runnable() {
@Override
public void run() {
if (!CameraDevice.this.isClosed()){
@@ -630,7 +650,10 @@
resultAsCapture);
}
}
- });
+ };
+ }
+
+ holder.getHandler().post(resultDispatch);
}
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index ed9264a..7ddfa87 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -521,7 +521,9 @@
int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0);
- if (savedInstanceState != null) {
+ // Restore from headers only if they are supported which
+ // is in multi-pane mode.
+ if (savedInstanceState != null && !mSinglePane) {
// We are restarting from a previous saved state; used that to
// initialize, instead of starting fresh.
ArrayList<Header> headers = savedInstanceState.getParcelableArrayList(HEADERS_TAG);
@@ -573,14 +575,12 @@
// 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) {
- initialTitleStr = getText(initialTitle);
- initialShortTitleStr = initialShortTitle != 0
+ CharSequence initialTitleStr = getText(initialTitle);
+ CharSequence 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/text/InputType.java b/core/java/android/text/InputType.java
index 6d066d6..c596388 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -46,9 +46,9 @@
* of text being given. Currently supported classes are:
* {@link #TYPE_CLASS_TEXT}, {@link #TYPE_CLASS_NUMBER},
* {@link #TYPE_CLASS_PHONE}, {@link #TYPE_CLASS_DATETIME}.
- * If the class is not one you
+ * <p>IME authors: If the class is not one you
* understand, assume {@link #TYPE_CLASS_TEXT} with NO variation
- * or flags.
+ * or flags.<p>
*/
public static final int TYPE_MASK_CLASS = 0x0000000f;
@@ -69,7 +69,10 @@
* This should be interpreted to mean that the target input connection
* is not rich, it can not process and show things like candidate text nor
* retrieve the current text, so the input method will need to run in a
- * limited "generate key events" mode.
+ * limited "generate key events" mode, if it supports it. Note that some
+ * input methods may not support it, for example a voice-based input
+ * method will likely not be able to generate key events even if this
+ * flag is set.
*/
public static final int TYPE_NULL = 0x00000000;
@@ -94,48 +97,70 @@
* Flag for {@link #TYPE_CLASS_TEXT}: capitalize all characters. Overrides
* {@link #TYPE_TEXT_FLAG_CAP_WORDS} and
* {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_CHARACTERS}.
+ * to be the same as {@link TextUtils#CAP_MODE_CHARACTERS}. Of course,
+ * this only affects languages where there are upper-case and lower-case letters.
*/
public static final int TYPE_TEXT_FLAG_CAP_CHARACTERS = 0x00001000;
/**
- * Flag for {@link #TYPE_CLASS_TEXT}: capitalize first character of
- * all words. Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This
+ * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of
+ * every word. Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This
* value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_WORDS}.
+ * to be the same as {@link TextUtils#CAP_MODE_WORDS}. Of course,
+ * this only affects languages where there are upper-case and lower-case letters.
*/
public static final int TYPE_TEXT_FLAG_CAP_WORDS = 0x00002000;
/**
- * Flag for {@link #TYPE_CLASS_TEXT}: capitalize first character of
+ * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of
* each sentence. This value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_SENTENCES}.
+ * to be the same as {@link TextUtils#CAP_MODE_SENTENCES}. For example
+ * in English it means to capitalize after a period and a space (note that other
+ * languages may have different characters for period, or not use spaces,
+ * or use different grammatical rules). Of course,
+ * this only affects languages where there are upper-case and lower-case letters.
*/
public static final int TYPE_TEXT_FLAG_CAP_SENTENCES = 0x00004000;
/**
* Flag for {@link #TYPE_CLASS_TEXT}: the user is entering free-form
- * text that should have auto-correction applied to it.
+ * text that should have auto-correction applied to it. Without this flag,
+ * the IME will not try to correct typos. You should always set this flag
+ * unless you really expect users to type non-words in this field, for
+ * example to choose a name for a character in a game.
+ * Contrast this with {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE} and
+ * {@link #TYPE_TEXT_FLAG_NO_SUGGESTIONS}:
+ * {@code TYPE_TEXT_FLAG_AUTO_CORRECT} means that the IME will try to
+ * auto-correct typos as the user is typing, but does not define whether
+ * the IME offers an interface to show suggestions.
*/
public static final int TYPE_TEXT_FLAG_AUTO_CORRECT = 0x00008000;
/**
- * Flag for {@link #TYPE_CLASS_TEXT}: the text editor is performing
- * auto-completion of the text being entered based on its own semantics,
- * which it will present to the user as they type. This generally means
- * that the input method should not be showing candidates itself, but can
- * expect for the editor to supply its own completions/candidates from
+ * Flag for {@link #TYPE_CLASS_TEXT}: the text editor (which means
+ * the application) is performing auto-completion of the text being entered
+ * based on its own semantics, which it will present to the user as they type.
+ * This generally means that the input method should not be showing
+ * candidates itself, but can expect the editor to supply its own
+ * completions/candidates from
* {@link android.view.inputmethod.InputMethodSession#displayCompletions
* InputMethodSession.displayCompletions()} as a result of the editor calling
* {@link android.view.inputmethod.InputMethodManager#displayCompletions
* InputMethodManager.displayCompletions()}.
+ * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and
+ * {@link #TYPE_TEXT_FLAG_NO_SUGGESTIONS}:
+ * {@code TYPE_TEXT_FLAG_AUTO_COMPLETE} means the editor should show an
+ * interface for displaying suggestions, but instead of supplying its own
+ * it will rely on the Editor to pass completions/corrections.
*/
public static final int TYPE_TEXT_FLAG_AUTO_COMPLETE = 0x00010000;
/**
* Flag for {@link #TYPE_CLASS_TEXT}: multiple lines of text can be
* entered into the field. If this flag is not set, the text field
- * will be constrained to a single line.
+ * will be constrained to a single line. The IME may also choose not to
+ * display an enter key when this flag is not set, as there should be no
+ * need to create new lines.
*/
public static final int TYPE_TEXT_FLAG_MULTI_LINE = 0x00020000;
@@ -152,6 +177,16 @@
* do not contain words from the language and do not benefit from any
* dictionary-based completions or corrections. It overrides the
* {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} value when set.
+ * Please avoid using this unless you are certain this is what you want.
+ * Many input methods need suggestions to work well, for example the ones
+ * based on gesture typing. Consider clearing
+ * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} instead if you just do not
+ * want the IME to correct typos.
+ * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and
+ * {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE}:
+ * {@code TYPE_TEXT_FLAG_NO_SUGGESTIONS} means the IME should never
+ * show an interface to display suggestions. Most IMEs will also take this to
+ * mean they should not try to auto-correct what the user is typing.
*/
public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000;
@@ -224,7 +259,9 @@
/**
* Variation of {@link #TYPE_CLASS_TEXT}: entering text for phonetic
- * pronunciation, such as a phonetic name field in contacts.
+ * pronunciation, such as a phonetic name field in contacts. This is mostly
+ * useful for languages where one spelling may have several phonetic
+ * readings, like Japanese.
*/
public static final int TYPE_TEXT_VARIATION_PHONETIC = 0x000000c0;
@@ -255,12 +292,13 @@
// ----------------------------------------------------------------------
/**
- * Class for numeric text. This class supports the following flag:
+ * Class for numeric text. This class supports the following flags:
* {@link #TYPE_NUMBER_FLAG_SIGNED} and
* {@link #TYPE_NUMBER_FLAG_DECIMAL}. It also supports the following
* variations: {@link #TYPE_NUMBER_VARIATION_NORMAL} and
- * {@link #TYPE_NUMBER_VARIATION_PASSWORD}. If you do not recognize
- * the variation, normal should be assumed.
+ * {@link #TYPE_NUMBER_VARIATION_PASSWORD}.
+ * <p>IME authors: If you do not recognize
+ * the variation, normal should be assumed.</p>
*/
public static final int TYPE_CLASS_NUMBER = 0x00000002;
@@ -318,7 +356,7 @@
* following variations:
* {@link #TYPE_DATETIME_VARIATION_NORMAL}
* {@link #TYPE_DATETIME_VARIATION_DATE}, and
- * {@link #TYPE_DATETIME_VARIATION_TIME},.
+ * {@link #TYPE_DATETIME_VARIATION_TIME}.
*/
public static final int TYPE_CLASS_DATETIME = 0x00000004;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 1b76cb1..c92a104 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -78,7 +78,8 @@
void addWindowToken(IBinder token, int type);
void removeWindowToken(IBinder token);
void addAppToken(int addPos, IApplicationToken token, int groupId, int stackId,
- int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId);
+ int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
+ int configChanges);
void setAppGroupId(IBinder token, int groupId);
void setAppOrientation(IApplicationToken token, int requestedOrientation);
int getAppOrientation(IApplicationToken token);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index aa2b0d4..99d5bbf 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -18,7 +18,6 @@
import android.content.ClipData;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -3102,7 +3101,15 @@
*/
private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
- private boolean mUseBackgroundPadding = false;
+ /**
+ * Cache if a left padding has been defined
+ */
+ private boolean mLeftPaddingDefined = false;
+
+ /**
+ * Cache if a right padding has been defined
+ */
+ private boolean mRightPaddingDefined = false;
/**
* @hide
@@ -3532,8 +3539,6 @@
int overScrollMode = mOverScrollMode;
boolean initializeScrollbars = false;
- boolean leftPaddingDefined = false;
- boolean rightPaddingDefined = false;
boolean startPaddingDefined = false;
boolean endPaddingDefined = false;
@@ -3550,13 +3555,13 @@
padding = a.getDimensionPixelSize(attr, -1);
mUserPaddingLeftInitial = padding;
mUserPaddingRightInitial = padding;
- leftPaddingDefined = true;
- rightPaddingDefined = true;
+ mLeftPaddingDefined = true;
+ mRightPaddingDefined = true;
break;
case com.android.internal.R.styleable.View_paddingLeft:
leftPadding = a.getDimensionPixelSize(attr, -1);
mUserPaddingLeftInitial = leftPadding;
- leftPaddingDefined = true;
+ mLeftPaddingDefined = true;
break;
case com.android.internal.R.styleable.View_paddingTop:
topPadding = a.getDimensionPixelSize(attr, -1);
@@ -3564,7 +3569,7 @@
case com.android.internal.R.styleable.View_paddingRight:
rightPadding = a.getDimensionPixelSize(attr, -1);
mUserPaddingRightInitial = rightPadding;
- rightPaddingDefined = true;
+ mRightPaddingDefined = true;
break;
case com.android.internal.R.styleable.View_paddingBottom:
bottomPadding = a.getDimensionPixelSize(attr, -1);
@@ -3884,11 +3889,11 @@
// Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
// and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
// defined.
- if (!leftPaddingDefined && startPaddingDefined) {
+ if (!mLeftPaddingDefined && startPaddingDefined) {
leftPadding = startPadding;
}
mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
- if (!rightPaddingDefined && endPaddingDefined) {
+ if (!mRightPaddingDefined && endPaddingDefined) {
rightPadding = endPadding;
}
mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
@@ -3900,10 +3905,10 @@
// defined.
final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
- if (leftPaddingDefined && !hasRelativePadding) {
+ if (mLeftPaddingDefined && !hasRelativePadding) {
mUserPaddingLeftInitial = leftPadding;
}
- if (rightPaddingDefined && !hasRelativePadding) {
+ if (mRightPaddingDefined && !hasRelativePadding) {
mUserPaddingRightInitial = rightPadding;
}
}
@@ -12347,15 +12352,19 @@
// 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) {
+ if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
Rect padding = sThreadLocal.get();
if (padding == null) {
padding = new Rect();
sThreadLocal.set(padding);
}
mBackground.getPadding(padding);
- mUserPaddingLeftInitial = padding.left;
- mUserPaddingRightInitial = padding.right;
+ if (!mLeftPaddingDefined) {
+ mUserPaddingLeftInitial = padding.left;
+ }
+ if (!mRightPaddingDefined) {
+ mUserPaddingRightInitial = padding.right;
+ }
}
switch (resolvedLayoutDirection) {
case LAYOUT_DIRECTION_RTL:
@@ -15352,9 +15361,6 @@
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
@@ -15380,8 +15386,6 @@
/* 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
@@ -15453,8 +15457,6 @@
mUserPaddingLeftInitial = left;
mUserPaddingRightInitial = right;
- mUseBackgroundPadding = false;
-
internalSetPadding(left, top, right, bottom);
}
@@ -15541,8 +15543,6 @@
mUserPaddingStart = start;
mUserPaddingEnd = end;
- mUseBackgroundPadding = false;
-
switch(getLayoutDirection()) {
case LAYOUT_DIRECTION_RTL:
mUserPaddingLeftInitial = end;
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 5146567..d4e005b 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -70,14 +70,14 @@
/**
* Bits of {@link #IME_MASK_ACTION}: the action key performs a "search"
* operation, taking the user to the results of searching for the text
- * the have typed (in whatever context is appropriate).
+ * they have typed (in whatever context is appropriate).
*/
public static final int IME_ACTION_SEARCH = 0x00000003;
/**
* Bits of {@link #IME_MASK_ACTION}: the action key performs a "send"
* operation, delivering the text to its target. This is typically used
- * when composing a message.
+ * when composing a message in IM or SMS where sending is immediate.
*/
public static final int IME_ACTION_SEND = 0x00000004;
@@ -89,22 +89,31 @@
/**
* Bits of {@link #IME_MASK_ACTION}: the action key performs a "done"
- * operation, typically meaning the IME will be closed.
+ * operation, typically meaning there is nothing more to input and the
+ * IME will be closed.
*/
public static final int IME_ACTION_DONE = 0x00000006;
/**
* Bits of {@link #IME_MASK_ACTION}: Like {@link #IME_ACTION_NEXT}, but
* for moving to the previous field. This will normally not be used to
- * specify an action (since it precludes {@link #IME_ACTION_NEXT}, but
+ * specify an action (since it precludes {@link #IME_ACTION_NEXT}), but
* can be returned to the app if it sets {@link #IME_FLAG_NAVIGATE_PREVIOUS}.
*/
public static final int IME_ACTION_PREVIOUS = 0x00000007;
/**
* Flag of {@link #imeOptions}: used to request that the IME never go
- * into fullscreen mode. Applications need to be aware that the flag is not
- * a guarantee, and not all IMEs will respect it.
+ * into fullscreen mode.
+ * By default, IMEs may go into full screen mode when they think
+ * it's appropriate, for example on small screens in landscape
+ * orientation where displaying a software keyboard may occlude
+ * such a large portion of the screen that the remaining part is
+ * too small to meaningfully display the application UI.
+ * If this flag is set, compliant IMEs will never go into full screen mode,
+ * and always leave some space to display the application UI.
+ * Applications need to be aware that the flag is not a guarantee, and
+ * some IMEs may ignore it.
*/
public static final int IME_FLAG_NO_FULLSCREEN = 0x2000000;
@@ -136,50 +145,56 @@
* Flag of {@link #imeOptions}: used to specify that the IME does not need
* to show its extracted text UI. For input methods that may be fullscreen,
* often when in landscape mode, this allows them to be smaller and let part
- * of the application be shown behind. Though there will likely be limited
- * access to the application available from the user, it can make the
- * experience of a (mostly) fullscreen IME less jarring. Note that when
- * this flag is specified the IME may <em>not</em> be set up to be able
- * to display text, so it should only be used in situations where this is
- * not needed.
+ * of the application be shown behind, through transparent UI parts in the
+ * fullscreen IME. The part of the UI visible to the user may not be responsive
+ * to touch because the IME will receive touch events, which may confuse the
+ * user; use {@link #IME_FLAG_NO_FULLSCREEN} instead for a better experience.
+ * Using this flag is discouraged and it may become deprecated in the future.
+ * Its meaning is unclear in some situations and it may not work appropriately
+ * on older versions of the platform.
*/
public static final int IME_FLAG_NO_EXTRACT_UI = 0x10000000;
/**
- * Flag of {@link #imeOptions}: used in conjunction with
- * {@link #IME_MASK_ACTION}, this indicates that the action should not
- * be available as an accessory button when the input method is full-screen.
- * Note that by setting this flag, there can be cases where the action
- * is simply never available to the user. Setting this generally means
- * that you think showing text being edited is more important than the
- * action you have supplied.
+ * Flag of {@link #imeOptions}: used in conjunction with one of the actions
+ * masked by {@link #IME_MASK_ACTION}, this indicates that the action
+ * should not be available as an accessory button on the right of the extracted
+ * text when the input method is full-screen. Note that by setting this flag,
+ * there can be cases where the action is simply never available to the
+ * user. Setting this generally means that you think that in fullscreen mode,
+ * where there is little space to show the text, it's not worth taking some
+ * screen real estate to display the action and it should be used instead
+ * to show more text.
*/
public static final int IME_FLAG_NO_ACCESSORY_ACTION = 0x20000000;
/**
- * Flag of {@link #imeOptions}: used in conjunction with
- * {@link #IME_MASK_ACTION}, this indicates that the action should not
- * be available in-line as a replacement for "enter" key. Typically this is
- * because the action has such a significant impact or is not recoverable
- * enough that accidentally hitting it should be avoided, such as sending
- * a message. Note that {@link android.widget.TextView} will automatically set this
- * flag for you on multi-line text views.
+ * Flag of {@link #imeOptions}: used in conjunction with one of the actions
+ * masked by {@link #IME_MASK_ACTION}. If this flag is not set, IMEs will
+ * normally replace the "enter" key with the action supplied. This flag
+ * indicates that the action should not be available in-line as a replacement
+ * for the "enter" key. Typically this is because the action has such a
+ * significant impact or is not recoverable enough that accidentally hitting
+ * it should be avoided, such as sending a message. Note that
+ * {@link android.widget.TextView} will automatically set this flag for you
+ * on multi-line text views.
*/
public static final int IME_FLAG_NO_ENTER_ACTION = 0x40000000;
/**
- * Flag of {@link #imeOptions}: used to request that the IME is capable of
+ * Flag of {@link #imeOptions}: used to request an IME that is capable of
* inputting ASCII characters. The intention of this flag is to ensure that
- * the user can type Roman alphabet characters in a {@link android.widget.TextView}
- * used for, typically, account ID or password input. It is expected that IMEs
- * normally are able to input ASCII even without being told so (such IMEs
- * already respect this flag in a sense), but there could be some cases they
- * aren't when, for instance, only non-ASCII input languagaes like Arabic,
- * Greek, Hebrew, Russian are enabled in the IME. Applications need to be
- * aware that the flag is not a guarantee, and not all IMEs will respect it.
+ * the user can type Roman alphabet characters in a {@link android.widget.TextView}.
+ * It is typically used for an account ID or password input. A lot of the time,
+ * IMEs are already able to input ASCII even without being told so (such IMEs
+ * already respect this flag in a sense), but there are cases when this is not
+ * the default. For instance, users of languages using a different script like
+ * Arabic, Greek, Hebrew or Russian typically have a keyboard that can't
+ * input ASCII characters by default. Applications need to be
+ * aware that the flag is not a guarantee, and some IMEs may not respect it.
* However, it is strongly recommended for IME authors to respect this flag
- * especially when their IME could end up with a state that has only non-ASCII
- * input languages enabled.
+ * especially when their IME could end up with a state where only languages
+ * using non-ASCII are enabled.
*/
public static final int IME_FLAG_FORCE_ASCII = 0x80000000;
@@ -209,8 +224,13 @@
/**
* In some cases an IME may be able to display an arbitrary label for
- * a command the user can perform, which you can specify here. You can
- * not count on this being used.
+ * a command the user can perform, which you can specify here. This is
+ * typically used as the label for the action to use in-line as a replacement
+ * for the "enter" key (see {@link #actionId}). Remember the key where
+ * this will be displayed is typically very small, and there are significant
+ * localization challenges to make this fit in all supported languages. Also
+ * you can not count absolutely on this being used, as some IMEs may
+ * ignore this.
*/
public CharSequence actionLabel = null;
@@ -224,13 +244,17 @@
/**
* The text offset of the start of the selection at the time editing
- * began; -1 if not known.
+ * began; -1 if not known. Keep in mind some IMEs may not be able
+ * to give their full feature set without knowing the cursor position;
+ * avoid passing -1 here if you can.
*/
public int initialSelStart = -1;
/**
* The text offset of the end of the selection at the time editing
- * began; -1 if not known.
+ * began; -1 if not known. Keep in mind some IMEs may not be able
+ * to give their full feature set without knowing the cursor position;
+ * avoid passing -1 here if you can.
*/
public int initialSelEnd = -1;
@@ -280,7 +304,7 @@
* Any extra data to supply to the input method. This is for extended
* communication with specific input methods; the name fields in the
* bundle should be scoped (such as "com.mydomain.im.SOME_FIELD") so
- * that they don't conflict with others. This field is can be
+ * that they don't conflict with others. This field can be
* filled in from the {@link android.R.attr#editorExtras}
* attribute of a TextView.
*/
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 59330ca..3537aec 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -142,7 +142,11 @@
* conditions in implementing this call. An IME can make a change
* to the text and use this method right away; you need to make
* sure the returned value is consistent with the result of the
- * latest edits.
+ * latest edits. Also, you may return less than n characters if performance
+ * dictates so, but keep in mind IMEs are relying on this for many
+ * functions: you should not, for example, limit the returned value to
+ * the current line, and specifically do not return 0 characters unless
+ * the cursor is really at the start of the text.</p>
*
* @param n The expected length of the text.
* @param flags Supplies additional options controlling how the text is
@@ -176,7 +180,11 @@
* conditions in implementing this call. An IME can make a change
* to the text and use this method right away; you need to make
* sure the returned value is consistent with the result of the
- * latest edits.</p>
+ * latest edits. Also, you may return less than n characters if performance
+ * dictates so, but keep in mind IMEs are relying on this for many
+ * functions: you should not, for example, limit the returned value to
+ * the current line, and specifically do not return 0 characters unless
+ * the cursor is really at the end of the text.</p>
*
* @param n The expected length of the text.
* @param flags Supplies additional options controlling how the text is
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialog.java b/core/java/com/android/internal/app/MediaRouteChooserDialog.java
index b963c74..944cc83 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialog.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialog.java
@@ -106,8 +106,8 @@
/**
* Returns true if the route should be included in the list.
* <p>
- * The default implementation returns true for non-default routes that
- * match the selector. Subclasses can override this method to filter routes
+ * The default implementation returns true for enabled non-default routes that
+ * match the route types. Subclasses can override this method to filter routes
* differently.
* </p>
*
@@ -115,7 +115,7 @@
* @return True if the route should be included in the chooser dialog.
*/
public boolean onFilterRoute(MediaRouter.RouteInfo route) {
- return !route.isDefault() && route.matchesTypes(mRouteTypes);
+ return !route.isDefault() && route.isEnabled() && route.matchesTypes(mRouteTypes);
}
@Override
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 5f9d8f2..786f5cf 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -526,7 +526,7 @@
if (mLogoNavItem != null) {
mLogoNavItem.setTitle(title);
}
- mUpGoerFive.setContentDescription(buildHomeContentDescription());
+ updateHomeAccessibility(mUpGoerFive.isEnabled());
}
public CharSequence getSubtitle() {
@@ -544,7 +544,7 @@
(!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle));
mTitleLayout.setVisibility(visible ? VISIBLE : GONE);
}
- mUpGoerFive.setContentDescription(buildHomeContentDescription());
+ updateHomeAccessibility(mUpGoerFive.isEnabled());
}
public void setHomeButtonEnabled(boolean enable) {
@@ -681,7 +681,7 @@
}
// Make sure the home button has an accurate content description for accessibility.
- updateHomeAccessibility(!mUpGoerFive.isEnabled());
+ updateHomeAccessibility(mUpGoerFive.isEnabled());
}
public void setIcon(Drawable icon) {
@@ -1332,11 +1332,13 @@
public void setHomeActionContentDescription(CharSequence description) {
mHomeDescription = description;
+ updateHomeAccessibility(mUpGoerFive.isEnabled());
}
public void setHomeActionContentDescription(int resId) {
mHomeDescriptionRes = resId;
mHomeDescription = resId != 0 ? getResources().getText(resId) : null;
+ updateHomeAccessibility(mUpGoerFive.isEnabled());
}
static class SavedState extends BaseSavedState {
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png
index b47d666..458a2a6 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png
index 13d803c..c91faa9 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png
index 3ae436b..14c9183 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png
index 24824fc..b388d86 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png
index af3819b..76c1323 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png
index 83dc251..fd39f9d 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png
index 8d9d592..c74727a 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png
index 1310ec9..826c9ae 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png
index 1705074..d0baec3 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png
index 7027b88..c60ff59 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png
index 7027b88..75552cc 100644
--- a/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_0.png b/core/res/res/drawable-hdpi/ic_notification_cast_0.png
new file mode 100644
index 0000000..a35f281
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_notification_cast_0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_1.png b/core/res/res/drawable-hdpi/ic_notification_cast_1.png
new file mode 100644
index 0000000..9f6e2ad
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_notification_cast_1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_2.png b/core/res/res/drawable-hdpi/ic_notification_cast_2.png
new file mode 100644
index 0000000..737137a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_notification_cast_2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_on.png b/core/res/res/drawable-hdpi/ic_notification_cast_on.png
new file mode 100644
index 0000000..ff2753a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_notification_cast_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png
index 6764598..9d92648 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png
index 94e0bb6..3e27fc8 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png
index 5ce2f20..72b9e78 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png
index 5105e90..bd462a2 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png
index 68c06ed..0a2cc89 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png
index 6e9b144..d162503 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png
index 45dc56f3d..997e32b 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png
index 46e743a..d314967 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png
index e384691..f15d7a9 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png
index e384691..26d46f8 100644
--- a/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_0.png b/core/res/res/drawable-mdpi/ic_notification_cast_0.png
new file mode 100644
index 0000000..d9cedbd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_notification_cast_0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_1.png b/core/res/res/drawable-mdpi/ic_notification_cast_1.png
new file mode 100644
index 0000000..414c67f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_notification_cast_1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_2.png b/core/res/res/drawable-mdpi/ic_notification_cast_2.png
new file mode 100644
index 0000000..280a888
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_notification_cast_2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_on.png b/core/res/res/drawable-mdpi/ic_notification_cast_on.png
new file mode 100644
index 0000000..ab5f1d7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_notification_cast_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png
index 1d48e12..045eee0 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png
index 2c8d1ec..6e14e29 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png
index 00b2043..121bbf6 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png
index ce1d939..468a0c3 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png
index 3064b46..414a322 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png
index 4316686..6088a48 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png
index 25c4e31..363d7d4 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png
index 8e32bd2..edf731e 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png
index aeaa78f..85cba7b 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png
index 85277fa..e65ac31 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png
index b01dbe8..d8e3e3a 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png
index c19a2ad..562dc9a 100644
--- a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_0.png b/core/res/res/drawable-xhdpi/ic_notification_cast_0.png
new file mode 100644
index 0000000..5fb23a0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_notification_cast_0.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_1.png b/core/res/res/drawable-xhdpi/ic_notification_cast_1.png
new file mode 100644
index 0000000..f01d17d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_notification_cast_1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_2.png b/core/res/res/drawable-xhdpi/ic_notification_cast_2.png
new file mode 100644
index 0000000..4f4ba7f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_notification_cast_2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_on.png b/core/res/res/drawable-xhdpi/ic_notification_cast_on.png
new file mode 100644
index 0000000..38f15dd
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_notification_cast_on.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png
index 7b0c383..178774c 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png
index efb624e..2dc2092 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png
index 5ee57e4..592ee8c 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png
index 6bc2e4a..f0549e2 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png
index c13af9c..91268f5 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png
index 744fb42..9d5436f 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png
index ca4d59c..8e77483 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png
index fde5688..f396d22 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png
index b8715c3..260bab4 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png
index 668bb25..2c9fb1d 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png
index 7f54a62..bdbd59c 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png
index 2df924d..f5c33dd 100644
--- a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png
new file mode 100644
index 0000000..f5b16ed
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png
new file mode 100644
index 0000000..22efeec
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png
new file mode 100644
index 0000000..e24cd97
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png
new file mode 100644
index 0000000..da1a627
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png
Binary files differ
diff --git a/core/res/res/drawable/ic_notification_cast_connecting.xml b/core/res/res/drawable/ic_notification_cast_connecting.xml
new file mode 100644
index 0000000..a390bce
--- /dev/null
+++ b/core/res/res/drawable/ic_notification_cast_connecting.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2013, 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.
+ */
+-->
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false">
+ <item android:drawable="@drawable/ic_notification_cast_0" android:duration="500" />
+ <item android:drawable="@drawable/ic_notification_cast_1" android:duration="500" />
+ <item android:drawable="@drawable/ic_notification_cast_2" android:duration="500" />
+ <item android:drawable="@drawable/ic_notification_cast_1" android:duration="500" />
+</animation-list>
diff --git a/core/res/res/layout/media_route_chooser_dialog.xml b/core/res/res/layout/media_route_chooser_dialog.xml
index 3eba9be..d1c6267 100644
--- a/core/res/res/layout/media_route_chooser_dialog.xml
+++ b/core/res/res/layout/media_route_chooser_dialog.xml
@@ -23,7 +23,8 @@
<!-- List of routes. -->
<ListView android:id="@+id/media_route_list"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
<!-- Content to show when list is empty. -->
<LinearLayout android:id="@android:id/empty"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index af5ace0..6d8a1c8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4143,10 +4143,14 @@
<!-- Title text to append when the display is secure. [CHAR LIMIT=30] -->
<string name="display_manager_overlay_display_secure_suffix">, secure</string>
+ <!-- Title of the notification to indicate the process of connecting to a wifi display. [CHAR LIMIT=50] -->
+ <string name="wifi_display_notification_connecting_title">Starting screen cast</string>
+ <!-- Message of the notification to indicate the process of connectig to a wifi display. [CHAR LIMIT=80] -->
+ <string name="wifi_display_notification_connecting_message">Connecting to <xliff:g id="name">%1$s</xliff:g></string>
<!-- Title of the notification to indicate an active wifi display connection. [CHAR LIMIT=50] -->
- <string name="wifi_display_notification_title">Wireless display is connected</string>
+ <string name="wifi_display_notification_connected_title">Screen cast in progress</string>
<!-- Message of the notification to indicate an active wifi display connection. [CHAR LIMIT=80] -->
- <string name="wifi_display_notification_message">This screen is showing on another device</string>
+ <string name="wifi_display_notification_connected_message">Connected to <xliff:g id="name">%1$s</xliff:g></string>
<!-- Label of a button to disconnect an active wifi display connection. [CHAR LIMIT=25] -->
<string name="wifi_display_notification_disconnect">Disconnect</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ee64bf9..d166ca6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1099,6 +1099,8 @@
<java-symbol type="drawable" name="ic_media_route_off_holo_dark" />
<java-symbol type="drawable" name="ic_media_route_connecting_holo_dark" />
<java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
+ <java-symbol type="drawable" name="ic_notification_cast_connecting" />
+ <java-symbol type="drawable" name="ic_notification_cast_on" />
<java-symbol type="drawable" name="cling_button" />
<java-symbol type="drawable" name="cling_arrow_up" />
<java-symbol type="drawable" name="cling_bg" />
@@ -1594,8 +1596,10 @@
<java-symbol type="string" name="vpn_lockdown_error" />
<java-symbol type="string" name="vpn_lockdown_config" />
<java-symbol type="string" name="wallpaper_binding_label" />
- <java-symbol type="string" name="wifi_display_notification_title" />
- <java-symbol type="string" name="wifi_display_notification_message" />
+ <java-symbol type="string" name="wifi_display_notification_connecting_title" />
+ <java-symbol type="string" name="wifi_display_notification_connecting_message" />
+ <java-symbol type="string" name="wifi_display_notification_connected_title" />
+ <java-symbol type="string" name="wifi_display_notification_connected_message" />
<java-symbol type="string" name="wifi_display_notification_disconnect" />
<java-symbol type="style" name="Theme.Dialog.AppError" />
<java-symbol type="style" name="Theme.Toast" />
diff --git a/data/sounds/AudioPackage11.mk b/data/sounds/AudioPackage11.mk
index b30be56..3c09297 100644
--- a/data/sounds/AudioPackage11.mk
+++ b/data/sounds/AudioPackage11.mk
@@ -17,19 +17,19 @@
$(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
$(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \
$(LOCAL_PATH)/effects/ogg/Effect_Tick_48k.ogg:system/media/audio/ui/Effect_Tick.ogg \
- $(LOCAL_PATH)/effects/ogg/KeypressStandard_120_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \
- $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
- $(LOCAL_PATH)/effects/ogg/KeypressDelete_120_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
- $(LOCAL_PATH)/effects/ogg/KeypressInvalid_120_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
- $(LOCAL_PATH)/effects/ogg/KeypressReturn_120_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressStandard_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressDelete_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
$(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
$(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
- $(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
- $(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \
$(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
$(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index fb753c5..3d10158 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -469,7 +469,7 @@
route.mDescription = globalRoute.description;
route.mSupportedTypes = globalRoute.supportedTypes;
route.mEnabled = globalRoute.enabled;
- route.setStatusCode(globalRoute.statusCode);
+ route.setRealStatusCode(globalRoute.statusCode);
route.mPlaybackType = globalRoute.playbackType;
route.mPlaybackStream = globalRoute.playbackStream;
route.mVolume = globalRoute.volume;
@@ -501,8 +501,8 @@
route.mEnabled = globalRoute.enabled;
changed = true;
}
- if (route.mStatusCode != globalRoute.statusCode) {
- route.setStatusCode(globalRoute.statusCode);
+ if (route.mRealStatusCode != globalRoute.statusCode) {
+ route.setRealStatusCode(globalRoute.statusCode);
changed = true;
}
if (route.mPlaybackType != globalRoute.playbackType) {
@@ -918,8 +918,14 @@
if (oldRoute != null) {
dispatchRouteUnselected(types & oldRoute.getSupportedTypes(), oldRoute);
+ if (oldRoute.resolveStatusCode()) {
+ dispatchRouteChanged(oldRoute);
+ }
}
if (route != null) {
+ if (route.resolveStatusCode()) {
+ dispatchRouteChanged(route);
+ }
dispatchRouteSelected(types & route.getSupportedTypes(), route);
}
}
@@ -1337,7 +1343,7 @@
newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
- newRoute.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
+ newRoute.setRealStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
newRoute.mEnabled = isWifiDisplayEnabled(display, wfdStatus);
newRoute.mName = display.getFriendlyDisplayName();
newRoute.mDescription = sStatic.mResources.getText(
@@ -1359,7 +1365,7 @@
changed |= route.mEnabled != enabled;
route.mEnabled = enabled;
- changed |= route.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
+ changed |= route.setRealStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
if (changed) {
dispatchRouteChanged(route);
@@ -1422,7 +1428,8 @@
String mGlobalRouteId;
// A predetermined connection status that can override mStatus
- private int mStatusCode;
+ private int mRealStatusCode;
+ private int mResolvedStatusCode;
/** @hide */ public static final int STATUS_NONE = 0;
/** @hide */ public static final int STATUS_SCANNING = 1;
@@ -1526,43 +1533,71 @@
* Set this route's status by predetermined status code. If the caller
* should dispatch a route changed event this call will return true;
*/
- boolean setStatusCode(int statusCode) {
- if (statusCode != mStatusCode) {
- mStatusCode = statusCode;
- int resId;
- switch (statusCode) {
- case STATUS_SCANNING:
- resId = com.android.internal.R.string.media_route_status_scanning;
- break;
- case STATUS_CONNECTING:
- resId = com.android.internal.R.string.media_route_status_connecting;
- break;
- case STATUS_AVAILABLE:
- resId = com.android.internal.R.string.media_route_status_available;
- break;
- case STATUS_NOT_AVAILABLE:
- resId = com.android.internal.R.string.media_route_status_not_available;
- break;
- case STATUS_IN_USE:
- resId = com.android.internal.R.string.media_route_status_in_use;
- break;
- case STATUS_CONNECTED:
- case STATUS_NONE:
- default:
- resId = 0;
- break;
- }
- mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null;
- return true;
+ boolean setRealStatusCode(int statusCode) {
+ if (mRealStatusCode != statusCode) {
+ mRealStatusCode = statusCode;
+ return resolveStatusCode();
}
return false;
}
/**
+ * Resolves the status code whenever the real status code or selection state
+ * changes.
+ */
+ boolean resolveStatusCode() {
+ int statusCode = mRealStatusCode;
+ if (isSelected()) {
+ switch (statusCode) {
+ // If the route is selected and its status appears to be between states
+ // then report it as connecting even though it has not yet had a chance
+ // to officially move into the CONNECTING state. Note that routes in
+ // the NONE state are assumed to not require an explicit connection
+ // lifecycle whereas those that are AVAILABLE are assumed to have
+ // to eventually proceed to CONNECTED.
+ case STATUS_AVAILABLE:
+ case STATUS_SCANNING:
+ statusCode = STATUS_CONNECTING;
+ break;
+ }
+ }
+ if (mResolvedStatusCode == statusCode) {
+ return false;
+ }
+
+ mResolvedStatusCode = statusCode;
+ int resId;
+ switch (statusCode) {
+ case STATUS_SCANNING:
+ resId = com.android.internal.R.string.media_route_status_scanning;
+ break;
+ case STATUS_CONNECTING:
+ resId = com.android.internal.R.string.media_route_status_connecting;
+ break;
+ case STATUS_AVAILABLE:
+ resId = com.android.internal.R.string.media_route_status_available;
+ break;
+ case STATUS_NOT_AVAILABLE:
+ resId = com.android.internal.R.string.media_route_status_not_available;
+ break;
+ case STATUS_IN_USE:
+ resId = com.android.internal.R.string.media_route_status_in_use;
+ break;
+ case STATUS_CONNECTED:
+ case STATUS_NONE:
+ default:
+ resId = 0;
+ break;
+ }
+ mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null;
+ return true;
+ }
+
+ /**
* @hide
*/
public int getStatusCode() {
- return mStatusCode;
+ return mResolvedStatusCode;
}
/**
@@ -1821,19 +1856,7 @@
* @return True if this route is in the process of connecting.
*/
public boolean isConnecting() {
- // If the route is selected and its status appears to be between states
- // then report it as connecting even though it has not yet had a chance
- // to move into the CONNECTING state. Note that routes in the NONE state
- // are assumed to not require an explicit connection lifecycle.
- if (isSelected()) {
- switch (mStatusCode) {
- case STATUS_AVAILABLE:
- case STATUS_SCANNING:
- case STATUS_CONNECTING:
- return true;
- }
- }
- return false;
+ return mResolvedStatusCode == STATUS_CONNECTING;
}
/** @hide */
diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
index 701c39c..e2df77c 100644
--- a/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
+++ b/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
@@ -16,6 +16,7 @@
package com.android.media.remotedisplay;
+import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@@ -27,6 +28,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.provider.Settings;
import android.util.ArrayMap;
import java.util.Collection;
@@ -95,6 +97,7 @@
private static final int MSG_SET_VOLUME = 5;
private static final int MSG_ADJUST_VOLUME = 6;
+ private final Context mContext;
private final ProviderStub mStub;
private final ProviderHandler mHandler;
private final ArrayMap<String, RemoteDisplay> mDisplays =
@@ -102,6 +105,8 @@
private IRemoteDisplayCallback mCallback;
private int mDiscoveryMode = DISCOVERY_MODE_NONE;
+ private PendingIntent mSettingsPendingIntent;
+
/**
* The {@link Intent} that must be declared as handled by the service.
* Put this in your manifest.
@@ -140,11 +145,19 @@
* @param context The application context for the remote display provider.
*/
public RemoteDisplayProvider(Context context) {
+ mContext = context;
mStub = new ProviderStub();
mHandler = new ProviderHandler(context.getMainLooper());
}
/**
+ * Gets the context of the remote display provider.
+ */
+ public final Context getContext() {
+ return mContext;
+ }
+
+ /**
* Gets the Binder associated with the provider.
* <p>
* This is intended to be used for the onBind() method of a service that implements
@@ -261,11 +274,29 @@
* Finds the remote display with the specified id, returns null if not found.
*
* @param id Id of the remote display.
+ * @return The display, or null if none.
*/
public RemoteDisplay findRemoteDisplay(String id) {
return mDisplays.get(id);
}
+ /**
+ * Gets a pending intent to launch the remote display settings activity.
+ *
+ * @return A pending intent to launch the settings activity.
+ */
+ public PendingIntent getSettingsPendingIntent() {
+ if (mSettingsPendingIntent == null) {
+ Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
+ settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mSettingsPendingIntent = PendingIntent.getActivity(
+ mContext, 0, settingsIntent, 0, null);
+ }
+ return mSettingsPendingIntent;
+ }
+
void setCallback(IRemoteDisplayCallback callback) {
mCallback = callback;
publishState();
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png
new file mode 100644
index 0000000..1c3518a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png
new file mode 100644
index 0000000..9dbc65e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png
new file mode 100644
index 0000000..ddb002d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png
new file mode 100644
index 0000000..43b7ef2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png
new file mode 100644
index 0000000..1d8b7ee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/search_light_land.png b/packages/SystemUI/res/drawable-hdpi/search_light_land.png
new file mode 100644
index 0000000..731f19b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/search_light_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png
new file mode 100644
index 0000000..11b2134
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png
new file mode 100644
index 0000000..a858573
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png
new file mode 100644
index 0000000..04de5d7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png
new file mode 100644
index 0000000..caea37e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png
new file mode 100644
index 0000000..b66aa46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/search_light_land.png b/packages/SystemUI/res/drawable-mdpi/search_light_land.png
new file mode 100644
index 0000000..a4d82f0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/search_light_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png
new file mode 100644
index 0000000..10ebcd5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png
new file mode 100644
index 0000000..fef43b8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png
new file mode 100644
index 0000000..05e3267
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png
new file mode 100644
index 0000000..ef42b27
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png
new file mode 100644
index 0000000..fc1c95e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/search_light_land.png b/packages/SystemUI/res/drawable-xhdpi/search_light_land.png
new file mode 100644
index 0000000..b62c74e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/search_light_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png
new file mode 100644
index 0000000..68b1b7c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png
new file mode 100644
index 0000000..8a8f890
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png
new file mode 100644
index 0000000..12d4a01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png
new file mode 100644
index 0000000..3cb4421
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png
new file mode 100644
index 0000000..4620b3a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/search_light_land.png b/packages/SystemUI/res/drawable-xxhdpi/search_light_land.png
new file mode 100644
index 0000000..f364577
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/search_light_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml b/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml
new file mode 100644
index 0000000..70db2a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2013, 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.
+ */
+-->
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false">
+ <item android:drawable="@drawable/ic_qs_cast_connecting_0" android:duration="500" />
+ <item android:drawable="@drawable/ic_qs_cast_connecting_1" android:duration="500" />
+ <item android:drawable="@drawable/ic_qs_cast_connecting_2" android:duration="500" />
+ <item android:drawable="@drawable/ic_qs_cast_connecting_1" android:duration="500" />
+</animation-list>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index aa365ae..5488a87 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -311,7 +311,7 @@
android:layout_height="80dp"
android:layout_width="match_parent"
android:layout_gravity="center_vertical"
- android:src="@drawable/search_light"
+ android:src="@drawable/search_light_land"
android:scaleType="center"
android:visibility="gone"
android:contentDescription="@string/accessibility_search_light"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e36ca8e..d39dc94 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -491,7 +491,7 @@
<!-- QuickSettings: Wifi (Off) [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_off_label">Wi-Fi Off</string>
<!-- QuickSettings: Remote display [CHAR LIMIT=NONE] -->
- <string name="quick_settings_remote_display_no_connection_label">Cast Screen</string>
+ <string name="quick_settings_remote_display_no_connection_label">Screen Cast</string>
<!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] -->
<string name="quick_settings_brightness_dialog_title">Brightness</string>
<!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/DessertCase.java b/packages/SystemUI/src/com/android/systemui/DessertCase.java
index dd4c018..d797e38 100644
--- a/packages/SystemUI/src/com/android/systemui/DessertCase.java
+++ b/packages/SystemUI/src/com/android/systemui/DessertCase.java
@@ -36,7 +36,8 @@
if (pm.getComponentEnabledSetting(cn) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
Slog.v("DessertCase", "ACHIEVEMENT UNLOCKED");
pm.setComponentEnabledSetting(cn,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
}
mView = new DessertCaseView(this);
diff --git a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
index 6fce732..4147155 100644
--- a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
@@ -496,7 +496,6 @@
}
public static class RescalingContainer extends FrameLayout {
- private static final int SYSTEM_UI_MODE_800 = 0x00000800;
private DessertCaseView mView;
private float mDarkness;
@@ -509,7 +508,7 @@
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | SYSTEM_UI_MODE_800
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index e59dfaa..e1a20ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -706,13 +706,11 @@
if (connectedRoute != null) {
mRemoteDisplayState.label = connectedRoute.getName().toString();
mRemoteDisplayState.iconId = connecting ?
- com.android.internal.R.drawable.ic_media_route_connecting_holo_dark :
- com.android.internal.R.drawable.ic_media_route_on_holo_dark;
+ R.drawable.ic_qs_cast_connecting : R.drawable.ic_qs_cast_connected;
} else {
mRemoteDisplayState.label = mContext.getString(
R.string.quick_settings_remote_display_no_connection_label);
- mRemoteDisplayState.iconId =
- com.android.internal.R.drawable.ic_media_route_off_holo_dark;
+ mRemoteDisplayState.iconId = R.drawable.ic_qs_cast_available;
}
mRemoteDisplayCallback.refreshView(mRemoteDisplayTile, mRemoteDisplayState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index dca5e41..6eb88be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -22,7 +22,7 @@
import android.graphics.Canvas;
import android.os.SystemClock;
import android.util.AttributeSet;
-import android.util.Log;
+import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
@@ -75,7 +75,7 @@
mVertical = (index == VERTICAL);
if (DEBUG)
- Log.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
+ Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
+ (mVertical ? " vertical" : " horizontal"));
setFlashOnTouchCapture(context.getResources().getBoolean(R.bool.config_dead_zone_flash));
@@ -106,7 +106,7 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
if (DEBUG) {
- Log.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
+ Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
}
final int action = event.getAction();
@@ -114,12 +114,12 @@
poke(event);
} else if (action == MotionEvent.ACTION_DOWN) {
if (DEBUG) {
- Log.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
+ Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
}
int size = (int) getSize(event.getEventTime());
if ((mVertical && event.getX() < size) || event.getY() < size) {
if (CHATTY) {
- Log.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
+ Slog.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")");
}
if (mShouldFlash) {
post(mDebugFlash);
@@ -134,7 +134,7 @@
public void poke(MotionEvent event) {
mLastPokeTime = event.getEventTime();
if (DEBUG)
- Log.v(TAG, "poked! size=" + getSize(mLastPokeTime));
+ Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
if (mShouldFlash) postInvalidate();
}
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 8cc80f7..1c3b9bb 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -522,6 +522,7 @@
|| pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) {
removed = true;
policy.mAdminList.remove(i);
+ policy.mAdminMap.remove(aa.info.getComponent());
}
} catch (RemoteException re) {
// Shouldn't happen
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 8eaa91d..399e7d1 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -123,6 +123,18 @@
# ---------------------------
# Out of memory for surfaces.
31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3)
+# Task created.
+31001 wm_task_created (TaskId|1|5),(StackId|1|5)
+# Task moved to top (1) or bottom (0).
+31002 wm_task_moved (TaskId|1|5),(ToTop|1),(Index|1)
+# Task removed with source explanation.
+31003 wm_task_removed (TaskId|1|5),(Reason|3)
+# Stack created.
+31004 wm_stack_created (StackId|1|5),(RelativeBoxId|1|5),(Position|1),(Weight|1|6)
+# Home stack moved to top (1) or bottom (0).
+31005 wm_home_stack_moved (ToTop|1)
+# Stack removed.
+31006 wm_stack_removed (StackId|1|5)
# ---------------------------
diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java
index e0f415b..16d2468 100644
--- a/services/java/com/android/server/NsdService.java
+++ b/services/java/com/android/server/NsdService.java
@@ -483,10 +483,14 @@
clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
stopResolveService(id);
- if (!getAddrInfo(id, cooked[3])) {
+ removeRequestMap(clientId, id, clientInfo);
+
+ int id2 = getUniqueId();
+ if (getAddrInfo(id2, cooked[3])) {
+ storeRequestMap(clientId, id2, clientInfo);
+ } else {
clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
NsdManager.FAILURE_INTERNAL_ERROR, clientId);
- removeRequestMap(clientId, id, clientInfo);
clientInfo.mResolvedService = null;
}
break;
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index c1a60ee..e25470c 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -40,6 +40,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.graphics.Point;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -637,6 +638,16 @@
return false;
}
+ private Point getDefaultDisplaySize() {
+ Point p = new Point();
+ try {
+ mIWindowManager.getInitialDisplaySize(Display.DEFAULT_DISPLAY, p);
+ } catch (RemoteException e) {
+ // not remote
+ }
+ return p;
+ }
+
public void setDimensionHints(int width, int height) throws RemoteException {
checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
synchronized (mLock) {
@@ -648,10 +659,10 @@
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("width and height must be > 0");
}
- // Make sure it is at least as large as the display's maximum size.
- int maxSizeDimension = getMaximumSizeDimension();
- width = Math.max(width, maxSizeDimension);
- height = Math.max(height, maxSizeDimension);
+ // Make sure it is at least as large as the display.
+ Point displaySize = getDefaultDisplaySize();
+ width = Math.max(width, displaySize.x);
+ height = Math.max(height, displaySize.y);
if (width != wallpaper.width || height != wallpaper.height) {
wallpaper.width = width;
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 569440d..fd791f9 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1717,7 +1717,7 @@
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
- r.userId);
+ r.userId, r.info.configChanges);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
@@ -1778,7 +1778,8 @@
r.updateOptionsLocked(options);
mWindowManager.addAppToken(task.mActivities.indexOf(r),
r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
- (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId);
+ (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
+ r.info.configChanges);
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
@@ -1821,7 +1822,8 @@
// because there is nothing for it to animate on top of.
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
- (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId);
+ (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
+ r.info.configChanges);
ActivityOptions.abort(options);
}
if (VALIDATE_TOKENS) {
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index 99f8ebb..11558a3 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -400,8 +400,6 @@
mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
refreshRate, deviceFlags, address, surface);
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
-
- scheduleUpdateNotificationLocked();
}
private void removeDisplayDeviceLocked() {
@@ -409,8 +407,6 @@
mDisplayDevice.destroyLocked();
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
mDisplayDevice = null;
-
- scheduleUpdateNotificationLocked();
}
}
@@ -457,21 +453,24 @@
// Runs on the handler.
private void handleUpdateNotification() {
- final boolean isConnected;
+ final int state;
+ final WifiDisplay display;
synchronized (getSyncRoot()) {
if (!mPendingNotificationUpdate) {
return;
}
mPendingNotificationUpdate = false;
- isConnected = (mDisplayDevice != null);
+ state = mActiveDisplayState;
+ display = mActiveDisplay;
}
// Cancel the old notification if there is one.
mNotificationManager.cancelAsUser(null,
- R.string.wifi_display_notification_title, UserHandle.ALL);
+ R.string.wifi_display_notification_disconnect, UserHandle.ALL);
- if (isConnected) {
+ if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING
+ || state == WifiDisplayStatus.DISPLAY_STATE_CONNECTED) {
Context context = getContext();
// Initialize pending intents for the notification outside of the lock because
@@ -493,20 +492,38 @@
// Post the notification.
Resources r = context.getResources();
- Notification notification = new Notification.Builder(context)
- .setContentTitle(r.getString(
- R.string.wifi_display_notification_title))
- .setContentText(r.getString(
- R.string.wifi_display_notification_message))
- .setContentIntent(mSettingsPendingIntent)
- .setSmallIcon(R.drawable.ic_media_route_on_holo_dark)
- .setOngoing(true)
- .addAction(android.R.drawable.ic_menu_close_clear_cancel,
- r.getString(R.string.wifi_display_notification_disconnect),
- mDisconnectPendingIntent)
- .build();
+ Notification notification;
+ if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING) {
+ notification = new Notification.Builder(context)
+ .setContentTitle(r.getString(
+ R.string.wifi_display_notification_connecting_title))
+ .setContentText(r.getString(
+ R.string.wifi_display_notification_connecting_message,
+ display.getFriendlyDisplayName()))
+ .setContentIntent(mSettingsPendingIntent)
+ .setSmallIcon(R.drawable.ic_notification_cast_connecting)
+ .setOngoing(true)
+ .addAction(android.R.drawable.ic_menu_close_clear_cancel,
+ r.getString(R.string.wifi_display_notification_disconnect),
+ mDisconnectPendingIntent)
+ .build();
+ } else {
+ notification = new Notification.Builder(context)
+ .setContentTitle(r.getString(
+ R.string.wifi_display_notification_connected_title))
+ .setContentText(r.getString(
+ R.string.wifi_display_notification_connected_message,
+ display.getFriendlyDisplayName()))
+ .setContentIntent(mSettingsPendingIntent)
+ .setSmallIcon(R.drawable.ic_notification_cast_on)
+ .setOngoing(true)
+ .addAction(android.R.drawable.ic_menu_close_clear_cancel,
+ r.getString(R.string.wifi_display_notification_disconnect),
+ mDisconnectPendingIntent)
+ .build();
+ }
mNotificationManager.notifyAsUser(null,
- R.string.wifi_display_notification_title,
+ R.string.wifi_display_notification_disconnect,
notification, UserHandle.ALL);
}
}
@@ -578,6 +595,7 @@
mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
mActiveDisplay = display;
scheduleStatusChangedBroadcastLocked();
+ scheduleUpdateNotificationLocked();
}
}
}
@@ -590,6 +608,7 @@
mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
mActiveDisplay = null;
scheduleStatusChangedBroadcastLocked();
+ scheduleUpdateNotificationLocked();
}
}
}
@@ -607,6 +626,7 @@
mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED;
mActiveDisplay = display;
scheduleStatusChangedBroadcastLocked();
+ scheduleUpdateNotificationLocked();
}
}
}
@@ -629,6 +649,7 @@
mActiveDisplay = display;
renameDisplayDeviceLocked(display.getFriendlyDisplayName());
scheduleStatusChangedBroadcastLocked();
+ scheduleUpdateNotificationLocked();
}
}
}
@@ -644,6 +665,7 @@
mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
mActiveDisplay = null;
scheduleStatusChangedBroadcastLocked();
+ scheduleUpdateNotificationLocked();
}
}
}
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
index 9a4cfb7..b2939fe 100644
--- a/services/java/com/android/server/display/WifiDisplayController.java
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -76,7 +76,7 @@
private static final int DEFAULT_CONTROL_PORT = 7236;
private static final int MAX_THROUGHPUT = 50;
private static final int CONNECTION_TIMEOUT_SECONDS = 60;
- private static final int RTSP_TIMEOUT_SECONDS = 15;
+ private static final int RTSP_TIMEOUT_SECONDS = 30;
private static final int RTSP_TIMEOUT_SECONDS_CERT_MODE = 120;
private static final int DISCOVER_PEERS_MAX_RETRIES = 10;
diff --git a/services/java/com/android/server/media/MediaRouterService.java b/services/java/com/android/server/media/MediaRouterService.java
index 2caab40..1491eb6 100644
--- a/services/java/com/android/server/media/MediaRouterService.java
+++ b/services/java/com/android/server/media/MediaRouterService.java
@@ -600,8 +600,16 @@
private static final int MSG_CONNECTION_TIMED_OUT = 9;
private static final int TIMEOUT_REASON_NOT_AVAILABLE = 1;
- private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTING = 2;
- private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTED = 3;
+ private static final int TIMEOUT_REASON_CONNECTION_LOST = 2;
+ private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTING = 3;
+ private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTED = 4;
+
+ // The relative order of these constants is important and expresses progress
+ // through the process of connecting to a route.
+ private static final int PHASE_NOT_AVAILABLE = -1;
+ private static final int PHASE_NOT_CONNECTED = 0;
+ private static final int PHASE_CONNECTING = 1;
+ private static final int PHASE_CONNECTED = 2;
private final MediaRouterService mService;
private final UserRecord mUserRecord;
@@ -614,6 +622,7 @@
private boolean mRunning;
private int mDiscoveryMode = RemoteDisplayState.DISCOVERY_MODE_NONE;
private RouteRecord mGloballySelectedRouteRecord;
+ private int mConnectionPhase = PHASE_NOT_AVAILABLE;
private int mConnectionTimeoutReason;
private long mConnectionTimeoutStartTime;
private boolean mClientStateUpdateScheduled;
@@ -675,6 +684,7 @@
pw.println(indent + "mRunning=" + mRunning);
pw.println(indent + "mDiscoveryMode=" + mDiscoveryMode);
pw.println(indent + "mGloballySelectedRouteRecord=" + mGloballySelectedRouteRecord);
+ pw.println(indent + "mConnectionPhase=" + mConnectionPhase);
pw.println(indent + "mConnectionTimeoutReason=" + mConnectionTimeoutReason);
pw.println(indent + "mConnectionTimeoutStartTime=" + (mConnectionTimeoutReason != 0 ?
TimeUtils.formatUptime(mConnectionTimeoutStartTime) : "<n/a>"));
@@ -843,6 +853,7 @@
private void checkGloballySelectedRouteState() {
// Unschedule timeouts when the route is unselected.
if (mGloballySelectedRouteRecord == null) {
+ mConnectionPhase = PHASE_NOT_AVAILABLE;
updateConnectionTimeout(0);
return;
}
@@ -854,29 +865,34 @@
return;
}
+ // Make sure we haven't lost our connection.
+ final int oldPhase = mConnectionPhase;
+ mConnectionPhase = getConnectionPhase(mGloballySelectedRouteRecord.getStatus());
+ if (oldPhase >= PHASE_CONNECTING && mConnectionPhase < PHASE_CONNECTING) {
+ updateConnectionTimeout(TIMEOUT_REASON_CONNECTION_LOST);
+ return;
+ }
+
// Check the route status.
- switch (mGloballySelectedRouteRecord.getStatus()) {
- case MediaRouter.RouteInfo.STATUS_NONE:
- case MediaRouter.RouteInfo.STATUS_CONNECTED:
- if (mConnectionTimeoutReason != 0) {
+ switch (mConnectionPhase) {
+ case PHASE_CONNECTED:
+ if (oldPhase != PHASE_CONNECTED) {
Slog.i(TAG, "Connected to global route: "
+ mGloballySelectedRouteRecord);
}
updateConnectionTimeout(0);
break;
- case MediaRouter.RouteInfo.STATUS_CONNECTING:
- if (mConnectionTimeoutReason != 0) {
+ case PHASE_CONNECTING:
+ if (oldPhase != PHASE_CONNECTING) {
Slog.i(TAG, "Connecting to global route: "
+ mGloballySelectedRouteRecord);
}
updateConnectionTimeout(TIMEOUT_REASON_WAITING_FOR_CONNECTED);
break;
- case MediaRouter.RouteInfo.STATUS_SCANNING:
- case MediaRouter.RouteInfo.STATUS_AVAILABLE:
+ case PHASE_NOT_CONNECTED:
updateConnectionTimeout(TIMEOUT_REASON_WAITING_FOR_CONNECTING);
break;
- case MediaRouter.RouteInfo.STATUS_NOT_AVAILABLE:
- case MediaRouter.RouteInfo.STATUS_IN_USE:
+ case PHASE_NOT_AVAILABLE:
default:
updateConnectionTimeout(TIMEOUT_REASON_NOT_AVAILABLE);
break;
@@ -892,7 +908,9 @@
mConnectionTimeoutStartTime = SystemClock.uptimeMillis();
switch (reason) {
case TIMEOUT_REASON_NOT_AVAILABLE:
- // Route became unavailable. Unselect it immediately.
+ case TIMEOUT_REASON_CONNECTION_LOST:
+ // Route became unavailable or connection lost.
+ // Unselect it immediately.
sendEmptyMessage(MSG_CONNECTION_TIMED_OUT);
break;
case TIMEOUT_REASON_WAITING_FOR_CONNECTING:
@@ -919,6 +937,10 @@
Slog.i(TAG, "Global route no longer available: "
+ mGloballySelectedRouteRecord);
break;
+ case TIMEOUT_REASON_CONNECTION_LOST:
+ Slog.i(TAG, "Global route connection lost: "
+ + mGloballySelectedRouteRecord);
+ break;
case TIMEOUT_REASON_WAITING_FOR_CONNECTING:
Slog.i(TAG, "Global route timed out while waiting for "
+ "connection attempt to begin after "
@@ -1004,6 +1026,23 @@
return null;
}
+ private static int getConnectionPhase(int status) {
+ switch (status) {
+ case MediaRouter.RouteInfo.STATUS_NONE:
+ case MediaRouter.RouteInfo.STATUS_CONNECTED:
+ return PHASE_CONNECTED;
+ case MediaRouter.RouteInfo.STATUS_CONNECTING:
+ return PHASE_CONNECTING;
+ case MediaRouter.RouteInfo.STATUS_SCANNING:
+ case MediaRouter.RouteInfo.STATUS_AVAILABLE:
+ return PHASE_NOT_CONNECTED;
+ case MediaRouter.RouteInfo.STATUS_NOT_AVAILABLE:
+ case MediaRouter.RouteInfo.STATUS_IN_USE:
+ default:
+ return PHASE_NOT_AVAILABLE;
+ }
+ }
+
static final class ProviderRecord {
private final RemoteDisplayProviderProxy mProvider;
private final String mUniquePrefix;
diff --git a/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java b/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java
index f3a3c2f..6a5f563 100644
--- a/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java
+++ b/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java
@@ -16,6 +16,7 @@
package com.android.server.media;
+import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -116,7 +117,7 @@
for (ResolveInfo resolveInfo : mPackageManager.queryIntentServicesAsUser(
intent, 0, mUserId)) {
ServiceInfo serviceInfo = resolveInfo.serviceInfo;
- if (serviceInfo != null) {
+ if (serviceInfo != null && verifyServiceTrusted(serviceInfo)) {
int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name);
if (sourceIndex < 0) {
RemoteDisplayProviderProxy provider =
@@ -146,6 +147,43 @@
}
}
+ private boolean verifyServiceTrusted(ServiceInfo serviceInfo) {
+ if (serviceInfo.permission == null || !serviceInfo.permission.equals(
+ Manifest.permission.BIND_REMOTE_DISPLAY)) {
+ // If the service does not require this permission then any app could
+ // potentially bind to it and cause the remote display service to
+ // misbehave. So we only want to trust providers that require the
+ // correct permissions.
+ Slog.w(TAG, "Ignoring remote display provider service because it did not "
+ + "require the BIND_REMOTE_DISPLAY permission in its manifest: "
+ + serviceInfo.packageName + "/" + serviceInfo.name);
+ return false;
+ }
+ if (!hasCaptureVideoPermission(serviceInfo.packageName)) {
+ // If the service does not have permission to capture video then it
+ // isn't going to be terribly useful as a remote display, is it?
+ // Kind of makes you wonder what it's doing there in the first place.
+ Slog.w(TAG, "Ignoring remote display provider service because it does not "
+ + "have the CAPTURE_VIDEO_OUTPUT or CAPTURE_SECURE_VIDEO_OUTPUT "
+ + "permission: " + serviceInfo.packageName + "/" + serviceInfo.name);
+ return false;
+ }
+ // Looks good.
+ return true;
+ }
+
+ private boolean hasCaptureVideoPermission(String packageName) {
+ if (mPackageManager.checkPermission(Manifest.permission.CAPTURE_VIDEO_OUTPUT,
+ packageName) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ if (mPackageManager.checkPermission(Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT,
+ packageName) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ return false;
+ }
+
private int findProvider(String packageName, String className) {
int count = mProviders.size();
for (int i = 0; i < count; i++) {
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 8cc1d02..b1d67de 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -53,6 +53,7 @@
int groupId = -1;
boolean appFullscreen;
int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ int configChanges;
boolean showWhenLocked;
// The input dispatching timeout for this application token in nanoseconds.
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 52f2325..d358b4c 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -25,9 +25,11 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Debug;
+import android.util.EventLog;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
+import com.android.server.EventLogTags;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -97,9 +99,6 @@
/** True when the home StackBox is at the top of mStackBoxes, false otherwise. */
private TaskStack mHomeStack = null;
- /** Sorted most recent at top, oldest at [0]. */
- ArrayList<TaskStack> mStackHistory = new ArrayList<TaskStack>();
-
/** Detect user tapping outside of current focused stack bounds .*/
StackTapPointerEventListener mTapDetector;
@@ -107,7 +106,7 @@
Region mTouchExcludeRegion = new Region();
/** Save allocating when retrieving tasks */
- ArrayList<Task> mTaskHistory = new ArrayList<Task>();
+ private ArrayList<Task> mTaskHistory = new ArrayList<Task>();
/** Save allocating when calculating rects */
Rect mTmpRect = new Rect();
@@ -160,12 +159,6 @@
return mStackBoxes.get(0).mStack != mHomeStack;
}
- void moveStack(TaskStack stack, boolean toTop) {
- mStackHistory.remove(stack);
- mStackHistory.add(toTop ? mStackHistory.size() : 0, stack);
- mService.moveStackWindowsLocked(this);
- }
-
public boolean isPrivate() {
return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
}
@@ -200,6 +193,7 @@
}
mTaskHistory.add(taskNdx, task);
+ EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, taskNdx);
}
void removeTask(Task task) {
@@ -277,6 +271,8 @@
if (newStack != null) {
layoutNeeded = true;
}
+ EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, relativeStackBoxId, position,
+ (int)(weight * 100 + 0.5));
return newStack;
}
@@ -345,6 +341,7 @@
boolean moveHomeStackBox(boolean toTop) {
if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop + " Callers=" +
Debug.getCallers(4));
+ EventLog.writeEvent(EventLogTags.WM_HOME_STACK_MOVED, toTop ? 1 : 0);
switch (mStackBoxes.size()) {
case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!");
case 1: return false; // Only the home StackBox exists.
diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java
index d054e9a..d351925 100644
--- a/services/java/com/android/server/wm/StackBox.java
+++ b/services/java/com/android/server/wm/StackBox.java
@@ -243,10 +243,6 @@
/** Remove this box and propagate its sibling's content up to their parent.
* @return The first stackId of the resulting StackBox. */
int remove() {
- if (mStack != null) {
- if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: removing stackId=" + mStack.mStackId);
- mDisplayContent.mStackHistory.remove(mStack);
- }
mDisplayContent.layoutNeeded = true;
if (mParent == null) {
diff --git a/services/java/com/android/server/wm/Task.java b/services/java/com/android/server/wm/Task.java
index d9acbb9..13fdbc8 100644
--- a/services/java/com/android/server/wm/Task.java
+++ b/services/java/com/android/server/wm/Task.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import android.util.EventLog;
+import com.android.server.EventLogTags;
+
class Task {
// private final String TAG = "TaskGroup";
TaskStack mStack;
@@ -41,6 +44,8 @@
boolean removeAppToken(AppWindowToken wtoken) {
mAppTokens.remove(wtoken);
if (mAppTokens.size() == 0) {
+ EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, taskId,
+ "removeAppToken: last token");
mStack.removeTask(this);
return true;
}
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 34bef68..e65aecb 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -21,8 +21,10 @@
import android.graphics.Rect;
import android.os.Debug;
+import android.util.EventLog;
import android.util.Slog;
import android.util.TypedValue;
+import com.android.server.EventLogTags;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
@@ -45,7 +47,7 @@
/** The Tasks that define this stack. Oldest Tasks are at the bottom. The ordering must match
* mTaskHistory in the ActivityStack with the same mStackId */
- private ArrayList<Task> mTasks = new ArrayList<Task>();
+ private final ArrayList<Task> mTasks = new ArrayList<Task>();
/** The StackBox this sits in. */
StackBox mStackBox;
@@ -70,7 +72,6 @@
mService = service;
mStackId = stackId;
mDisplayContent = displayContent;
- final int displayId = displayContent.getDisplayId();
mDimLayer = new DimLayer(service, this);
mAnimationBackgroundSurface = new DimLayer(service, this);
}
@@ -152,6 +153,7 @@
int remove() {
mAnimationBackgroundSurface.destroySurface();
mDimLayer.destroySurface();
+ EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
return mStackBox.remove();
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 818cfec..1395eda 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3397,16 +3397,17 @@
if (stack == null) {
throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
}
+ EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
Task task = new Task(atoken, stack, userId);
mTaskIdToTask.put(taskId, task);
stack.addTask(task, true);
- stack.getDisplayContent().moveStack(stack, true);
return task;
}
@Override
public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
- int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId) {
+ int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
+ int configChanges) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"addAppToken()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -3438,6 +3439,7 @@
atoken.appFullscreen = fullscreen;
atoken.showWhenLocked = showWhenLocked;
atoken.requestedOrientation = requestedOrientation;
+ atoken.configChanges = configChanges;
if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
+ " to stack=" + stackId + " task=" + taskId + " at " + addPos);
@@ -4791,7 +4793,6 @@
displayContent.moveHomeStackBox(isHomeStackTask);
}
stack.moveTaskToTop(task);
- displayContent.moveStack(stack, true);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -4845,7 +4846,6 @@
weight);
if (stack != null) {
mStackIdToStack.put(stackId, stack);
- displayContent.moveStack(stack, true);
performLayoutAndPlaceSurfacesLocked();
return;
}
@@ -4877,6 +4877,7 @@
return;
}
final TaskStack stack = task.mStack;
+ EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
stack.removeTask(task);
stack.getDisplayContent().layoutNeeded = true;
}
@@ -8268,8 +8269,10 @@
// 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()
- || mOpeningApps.contains(win.mAppToken)
+ || win.isConfigChanged() && (win.mAttrs.type == TYPE_KEYGUARD ||
+ (win.mAppToken != null && (win.mAppToken.configChanges &
+ (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION))
+ != 0))
|| win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
if (!win.mLayoutAttached) {
if (initial) {
diff --git a/tests/RemoteDisplayProvider/Android.mk b/tests/RemoteDisplayProvider/Android.mk
index 77e9815..2f4b343 100644
--- a/tests/RemoteDisplayProvider/Android.mk
+++ b/tests/RemoteDisplayProvider/Android.mk
@@ -22,4 +22,5 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
LOCAL_JAVA_LIBRARIES := com.android.media.remotedisplay
+LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
diff --git a/tests/RemoteDisplayProvider/AndroidManifest.xml b/tests/RemoteDisplayProvider/AndroidManifest.xml
index e8e31da..afb7c78 100644
--- a/tests/RemoteDisplayProvider/AndroidManifest.xml
+++ b/tests/RemoteDisplayProvider/AndroidManifest.xml
@@ -18,6 +18,7 @@
package="com.android.media.remotedisplay.test" >
<uses-sdk android:minSdkVersion="19" />
+ <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"/>
<application android:label="@string/app_name"
android:icon="@drawable/ic_app">
diff --git a/tests/RemoteDisplayProvider/src/com/android/media/remotedisplay/test/RemoteDisplayProviderService.java b/tests/RemoteDisplayProvider/src/com/android/media/remotedisplay/test/RemoteDisplayProviderService.java
index bf84631..611d7e4 100644
--- a/tests/RemoteDisplayProvider/src/com/android/media/remotedisplay/test/RemoteDisplayProviderService.java
+++ b/tests/RemoteDisplayProvider/src/com/android/media/remotedisplay/test/RemoteDisplayProviderService.java
@@ -52,6 +52,9 @@
private RemoteDisplay mTestDisplay5; // available but ignores request to connect
private RemoteDisplay mTestDisplay6; // available but never finishes connecting
private RemoteDisplay mTestDisplay7; // blinks in and out of existence
+ private RemoteDisplay mTestDisplay8; // available but connecting attempt flakes out
+ private RemoteDisplay mTestDisplay9; // available but connection flakes out
+ private RemoteDisplay mTestDisplay10; // available and reconnects periodically
private final Handler mHandler;
private boolean mBlinking;
@@ -112,6 +115,27 @@
mTestDisplay6.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay6);
}
+ if (mTestDisplay8 == null) {
+ mTestDisplay8 = new RemoteDisplay("testDisplay8",
+ "Test Display 8 (flaky when connecting)");
+ mTestDisplay8.setDescription("Aborts spontaneously while connecting");
+ mTestDisplay8.setStatus(RemoteDisplay.STATUS_AVAILABLE);
+ addDisplay(mTestDisplay8);
+ }
+ if (mTestDisplay9 == null) {
+ mTestDisplay9 = new RemoteDisplay("testDisplay9",
+ "Test Display 9 (flaky when connected)");
+ mTestDisplay9.setDescription("Aborts spontaneously while connected");
+ mTestDisplay9.setStatus(RemoteDisplay.STATUS_AVAILABLE);
+ addDisplay(mTestDisplay9);
+ }
+ if (mTestDisplay10 == null) {
+ mTestDisplay10 = new RemoteDisplay("testDisplay10",
+ "Test Display 10 (reconnects periodically)");
+ mTestDisplay10.setDescription("Reconnects spontaneously");
+ mTestDisplay10.setStatus(RemoteDisplay.STATUS_AVAILABLE);
+ addDisplay(mTestDisplay10);
+ }
} else {
// When discovery ends, go hide some of the routes we can't actually use.
// This isn't something a normal route provider would do though.
@@ -144,6 +168,7 @@
if (display == mTestDisplay1 || display == mTestDisplay2) {
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
+ updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
@@ -154,12 +179,67 @@
}
}
}, 2000);
- updateDisplay(display);
- }
- if (display == mTestDisplay6 || display == mTestDisplay7) {
+ } else if (display == mTestDisplay6 || display == mTestDisplay7) {
// never finishes connecting
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
+ } else if (display == mTestDisplay8) {
+ // flakes out while connecting
+ display.setStatus(RemoteDisplay.STATUS_CONNECTING);
+ updateDisplay(display);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if ((display == mTestDisplay8)
+ && display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
+ display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
+ updateDisplay(display);
+ }
+ }
+ }, 2000);
+ } else if (display == mTestDisplay9) {
+ // flakes out when connected
+ display.setStatus(RemoteDisplay.STATUS_CONNECTING);
+ updateDisplay(display);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if ((display == mTestDisplay9)
+ && display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
+ display.setStatus(RemoteDisplay.STATUS_CONNECTED);
+ updateDisplay(display);
+ }
+ }
+ }, 2000);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if ((display == mTestDisplay9)
+ && display.getStatus() == RemoteDisplay.STATUS_CONNECTED) {
+ display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
+ updateDisplay(display);
+ }
+ }
+ }, 5000);
+ } else if (display == mTestDisplay10) {
+ display.setStatus(RemoteDisplay.STATUS_CONNECTING);
+ updateDisplay(display);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (display == mTestDisplay10) {
+ if (display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
+ display.setStatus(RemoteDisplay.STATUS_CONNECTED);
+ updateDisplay(display);
+ mHandler.postDelayed(this, 7000);
+ } else if (display.getStatus() == RemoteDisplay.STATUS_CONNECTED) {
+ display.setStatus(RemoteDisplay.STATUS_CONNECTING);
+ updateDisplay(display);
+ mHandler.postDelayed(this, 2000);
+ }
+ }
+ }
+ }, 2000);
}
}
@@ -168,7 +248,8 @@
Log.d(TAG, "onDisconnect: display.getId()=" + display.getId());
if (display == mTestDisplay1 || display == mTestDisplay2
- || display == mTestDisplay6) {
+ || display == mTestDisplay6 || display == mTestDisplay8
+ || display == mTestDisplay9 || display == mTestDisplay10) {
display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
updateDisplay(display);
}
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index e4c4214..df32ee1 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -93,7 +93,7 @@
}
try {
- mWm.addAppToken(0, null, 0, 0, 0, false, false, 0);
+ mWm.addAppToken(0, null, 0, 0, 0, false, false, 0, 0);
fail("IWindowManager.addAppToken did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index ec284ac..93284db 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -308,8 +308,9 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeRecycle(int nativeBitmap) {
+ /*package*/ static boolean nativeRecycle(int nativeBitmap) {
sManager.removeJavaReferenceFor(nativeBitmap);
+ return true;
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index fd153af..dd2cbc1 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -81,7 +81,7 @@
@Override
public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4,
- boolean arg5, boolean arg6, int arg7)
+ boolean arg5, boolean arg6, int arg7, int arg8)
throws RemoteException {
// TODO Auto-generated method stub