Merge "Add null check in showLockTaskToast" into nyc-dev
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 4a1aff7..02eb4d3 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -284,7 +284,7 @@
}
public boolean startExitBackTransition(final Activity activity) {
- if (mEnteringNames == null) {
+ if (mEnteringNames == null || mCalledExitCoordinator != null) {
return false;
} else {
if (!mHasExited) {
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 02dcc5c..2ae437e 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -28,12 +28,12 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import libcore.util.ZoneInfoDB;
import java.io.IOException;
-import java.util.WeakHashMap;
/**
* This class provides access to the system alarm services. These allow you
@@ -244,7 +244,7 @@
// Tracking of the OnAlarmListener -> wrapper mapping, for cancel() support.
// Access is synchronized on the AlarmManager class object.
- private static WeakHashMap<OnAlarmListener, ListenerWrapper> sWrappers;
+ private static ArrayMap<OnAlarmListener, ListenerWrapper> sWrappers;
/**
* package private on purpose
@@ -631,7 +631,7 @@
if (listener != null) {
synchronized (AlarmManager.class) {
if (sWrappers == null) {
- sWrappers = new WeakHashMap<OnAlarmListener, ListenerWrapper>();
+ sWrappers = new ArrayMap<OnAlarmListener, ListenerWrapper>();
}
recipientWrapper = sWrappers.get(listener);
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index a599584..8bf1e9a 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -150,6 +150,7 @@
}
};
decor.getViewTreeObserver().addOnPreDrawListener(mViewsReadyListener);
+ decor.invalidate();
}
}
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 6e6baea..3069e5a 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -21,9 +21,9 @@
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
import android.widget.RemoteViews;
@@ -230,6 +230,7 @@
public void setOnClickListener(@Nullable OnClickListener l) {
mExpandClickListener = l;
setOnTouchListener(mExpandClickListener != null ? mTouchListener : null);
+ setFocusable(l != null);
updateTouchListener();
}
@@ -379,6 +380,19 @@
return this;
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ if (mExpandClickListener != null) {
+ AccessibilityNodeInfo.AccessibilityAction expand
+ = new AccessibilityNodeInfo.AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_CLICK,
+ getContext().getString(
+ com.android.internal.R.string.expand_action_accessibility));
+ info.addAction(expand);
+ }
+ }
+
public ImageView getExpandButton() {
return mExpandButton;
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 28ade80..b331be7 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2675,19 +2675,49 @@
return (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK ? 0 : mPaddingBottom;
}
+ /**
+ * @hide
+ */
+ @Override
+ protected void internalSetPadding(int left, int top, int right, int bottom) {
+ super.internalSetPadding(left, top, right, bottom);
+ if (isLayoutRequested()) {
+ handleBoundsChange();
+ }
+ }
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- if (getChildCount() > 0) {
- mDataChanged = true;
- rememberSyncState();
- }
-
+ handleBoundsChange();
if (mFastScroll != null) {
mFastScroll.onSizeChanged(w, h, oldw, oldh);
}
}
/**
+ * Called when bounds of the AbsListView are changed. AbsListView marks data set as changed
+ * and force layouts all children that don't have exact measure specs.
+ * <p>
+ * This invalidation is necessary, otherwise, AbsListView may think the children are valid and
+ * fail to relayout them properly to accommodate for new bounds.
+ */
+ void handleBoundsChange() {
+ final int childCount = getChildCount();
+ if (childCount > 0) {
+ mDataChanged = true;
+ rememberSyncState();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ final ViewGroup.LayoutParams lp = child.getLayoutParams();
+ // force layout child unless it has exact specs
+ if (lp == null || lp.width < 1 || lp.height < 1) {
+ child.forceLayout();
+ }
+ }
+ }
+ }
+
+ /**
* @return True if the current touch mode requires that we draw the selector in the pressed
* state.
*/
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index f596636..a065219 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -45,6 +45,7 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Shader;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.RemoteException;
import android.util.DisplayMetrics;
@@ -907,10 +908,12 @@
if (getBackground() != drawable) {
setBackgroundDrawable(drawable);
if (drawable != null) {
- mResizingBackgroundDrawable = drawable;
+ mResizingBackgroundDrawable = enforceNonTranslucentBackground(drawable,
+ mWindow.isTranslucent() || mWindow.isShowingWallpaper());
} else {
mResizingBackgroundDrawable = getResizingBackgroundDrawable(
- getContext(), 0, mWindow.mBackgroundFallbackResource);
+ getContext(), 0, mWindow.mBackgroundFallbackResource,
+ mWindow.isTranslucent() || mWindow.isShowingWallpaper());
}
if (mResizingBackgroundDrawable != null) {
mResizingBackgroundDrawable.getPadding(mBackgroundPadding);
@@ -1785,7 +1788,8 @@
private void loadBackgroundDrawablesIfNeeded() {
if (mResizingBackgroundDrawable == null) {
mResizingBackgroundDrawable = getResizingBackgroundDrawable(getContext(),
- mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource);
+ mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource,
+ mWindow.isTranslucent() || mWindow.isShowingWallpaper());
if (mResizingBackgroundDrawable == null) {
// We shouldn't really get here as the background fallback should be always
// available since it is defaulted by the system.
@@ -1893,21 +1897,41 @@
* user is resizing the window of an activity in multi-window mode.
*/
public static Drawable getResizingBackgroundDrawable(Context context, int backgroundRes,
- int backgroundFallbackRes) {
+ int backgroundFallbackRes, boolean windowTranslucent) {
if (backgroundRes != 0) {
final Drawable drawable = context.getDrawable(backgroundRes);
if (drawable != null) {
- return drawable;
+ return enforceNonTranslucentBackground(drawable, windowTranslucent);
}
}
if (backgroundFallbackRes != 0) {
final Drawable fallbackDrawable = context.getDrawable(backgroundFallbackRes);
if (fallbackDrawable != null) {
- return fallbackDrawable;
+ return enforceNonTranslucentBackground(fallbackDrawable, windowTranslucent);
}
}
- return null;
+ return new ColorDrawable(Color.BLACK);
+ }
+
+ /**
+ * Enforces a drawable to be non-translucent to act as a background if needed, i.e. if the
+ * window is not translucent.
+ */
+ private static Drawable enforceNonTranslucentBackground(Drawable drawable,
+ boolean windowTranslucent) {
+ if (!windowTranslucent && drawable instanceof ColorDrawable) {
+ ColorDrawable colorDrawable = (ColorDrawable) drawable;
+ int color = colorDrawable.getColor();
+ if (Color.alpha(color) != 255) {
+ ColorDrawable copy = (ColorDrawable) colorDrawable.getConstantState().newDrawable()
+ .mutate();
+ copy.setColor(
+ Color.argb(255, Color.red(color), Color.green(color), Color.blue(color)));
+ return copy;
+ }
+ }
+ return drawable;
}
/**
@@ -2037,7 +2061,7 @@
private void drawResizingShadowIfNeeded(DisplayListCanvas canvas) {
if (mResizeMode != RESIZE_MODE_DOCKED_DIVIDER || mWindow.mIsFloating
|| mWindow.isTranslucent()
- || (mWindow.getAttributes().flags & FLAG_SHOW_WALLPAPER) != 0) {
+ || mWindow.isShowingWallpaper()) {
return;
}
canvas.save();
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 4f15ece..9ad750d 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -509,6 +509,13 @@
}
/**
+ * @return Whether the window is currently showing the wallpaper.
+ */
+ boolean isShowingWallpaper() {
+ return (getAttributes().flags & FLAG_SHOW_WALLPAPER) != 0;
+ }
+
+ /**
* Return a LayoutInflater instance that can be used to inflate XML view layout
* resources for use in this Window.
*
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3a28822..4649e9d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4263,7 +4263,7 @@
<string name="expand_button_content_description">Expand button</string>
<!-- Accessibility action description on the expand button. -->
- <string name="expand_action_accessibility">Click to expand</string>
+ <string name="expand_action_accessibility">toggle expansion</string>
<!-- User visible name for USB MIDI Peripheral port -->
<string name="usb_midi_peripheral_name">Android USB Peripheral Port</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9ab42a9..9dbe100 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2566,6 +2566,7 @@
<!-- WallpaperManager config -->
<java-symbol type="string" name="config_wallpaperCropperPackage" />
+ <java-symbol type="string" name="expand_action_accessibility" />
<java-symbol type="id" name="textSpacerNoTitle" />
<java-symbol type="id" name="titleDividerNoCustom" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 998eea5..aecda44 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -174,7 +174,6 @@
<!-- Window attributes -->
<item name="windowBackground">@drawable/screen_background_selector_dark</item>
- <item name="windowBackgroundFallback">?attr/colorBackground</item>
<item name="windowClipToOutline">false</item>
<item name="windowFrame">@null</item>
<item name="windowNoTitle">false</item>
diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd
index 384cb0a..543313a 100644
--- a/docs/html/wear/preview/api-overview.jd
+++ b/docs/html/wear/preview/api-overview.jd
@@ -147,7 +147,7 @@
<p> If you have a chat messaging app, your notifications should use
{@code Notification.MessagingStyle}, which is new in Android 6.0. Wear 2.0 uses
the chat messages included in a
-<a href="{docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a>
+<a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a>
notification
(see {@code addMessage()}) to provide a rich chat app-like experience in the
expanded notification.
diff --git a/docs/html/wear/preview/features/notifications.jd b/docs/html/wear/preview/features/notifications.jd
index 0962eb4..75f9fee 100644
--- a/docs/html/wear/preview/features/notifications.jd
+++ b/docs/html/wear/preview/features/notifications.jd
@@ -41,7 +41,7 @@
</p>
<p><img src="{@docRoot}wear/preview/images/comparison_diagram.png" /> </p>
-<p><b>Figure 1.</b> Comparison of the same notification in Android Wear 1.x and 2.0.</p>
+<p><b>Figure 1.</b> Comparison of the same notification in Android Wear 1.x and 2.0.</p>
<p>Some of the visual updates include:</p>
<ul>
@@ -73,7 +73,7 @@
<li><strong>Updated horizontal swipe gesture on a notification</strong>:
To dismiss a notification in Wear 2.0, the user swipes horizontally in either
- direction. So if your notification instructs the user to swipe left or right,
+ direction. So if your notification instructs the user to swipe left or right,
you must update the text of your notification.
</li>
</ul>
@@ -82,13 +82,14 @@
substantial additional content and actions for each notification.
</p>
<p>When you <a href="{@docRoot}training/wearables/notifications/pages.html">specify additional content pages</a>
- and actions for a notification, those are available to the user within the
- expanded notification. Each expanded notification follows
+ and actions for a notification, those are available to the user within the
+ expanded notification. Each expanded notification follows
<a href="http://www.google.com/design/spec-wear">Material Design for Android Wear</a>,
so the user gets an app-like experience.
</p>
-<p><img src="{@docRoot}wear/preview/images/expanded_diagram.png" /> </p>
-<p><b>Figure 2</b>. An expanded notification with content and actions.</p>
+
+
+<h3 id="expanded">Expanded notifications</h3>
<p>If the first action in the expanded notification has a
<a href=" {@docRoot}reference/android/support/v4/app/RemoteInput.html">{@code RemoteInput}</a>
(e.g., a Reply action), then the choices you set with <a href="http://developer.android.com/reference/android/support/v4/app/RemoteInput.Builder.html#setChoices(java.lang.CharSequence[])">{@code setChoices()}</a>
@@ -102,7 +103,7 @@
<li>The notification is generated by an app on the paired phone and
bridged to Wear.
</li>
- <li>The notification does not have a
+ <li>The notification does not have a
<a href="http://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">{@code contentIntent}</a>.
</li>
</ul>
@@ -126,9 +127,11 @@
<p>
Expanded Notifications allow you to include additional content and actions
for a notification. You choose the level of detail that your app's notifications
- will provide; however be judicious with the amount of detail you include in a
- notification.
+ will provide; however be judicious with the amount of detail you include in a
+ notification.
</p>
+<img src="{@docRoot}wear/preview/images/expanded_diagram.png" height="340"
+ style="float:left;margin:10px 20px 0 0" />
<h4>Adding additional content</h4>
To show additional content in your expanded notification, see <a href="{@docRoot}training/wearables/notifications/pages.html">Adding Pages to a Notification</a>.</p>
<p>Additional content pages are stacked vertically in the expanded notification
@@ -151,34 +154,36 @@
<p>If you have a chat messaging app, your notifications should use
<a href="{@docRoot}preview/features/notification-updates.html#style">{@code Notification.MessagingStyle}</a>,
- which is new in Android 6.0. Wear 2.0 uses the chat messages included
+ which is new in Android N. Wear 2.0 uses the chat messages included
in a <a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a> notification
+
(see <a href="{@docRoot}preview/features/notification-updates.html#style">{@code addMessage()}</a>) to provide
a rich chat app-like experience in the expanded notification.
</p>
-<p class="note">Note: <a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a>
+
+<p class="note">Note: <a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a>
expanded notifications require that you have at least version 1.5.0.2861804 of the
<a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app">Android Wear app</a>
on your paired Android phone. That version will be available within the next
few weeks in the Play Store.
</p>
+
<h3 id="smart-reply">Smart Reply</h3>
-<p>Wear 2.0 also introduces <i>Smart Reply</i> for <a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a> notifications.
+<img src="{@docRoot}wear/preview/images/messaging_style.png" height="420"
+ style="float:right;margin:10px 20px 0 0" />
+<p>Wear 2.0 also introduces <i>Smart Reply</i>
+for <a href="{@docRoot}preview/features/notification-updates.html#style">{@code MessagingStyle}</a> notifications.
Smart Reply provides the user with contextually relevant, touchable choices in
the expanded notification and in {@code RemoteInput}. These augment the fixed
- list of choices that the developer provides in
+ list of choices that the developer provides in
<a href="http://developer.android.com/reference/android/support/v4/app/RemoteInput.html">{@code RemoteInput}</a>
- using the
+ using the
<a href="{@docRoot}reference/android/support/v4/app/RemoteInput.Builder.html#setChoices(java.lang.CharSequence[])">{@code setChoices()}</a> method.
</p>
<p>By enabling Smart Reply for your MessagingStyle notifications,
you provide users with a fast (single tap), discreet (no speaking aloud), and
reliable way to respond to chat messages.
</p>
-<p><img src="{@docRoot}wear/preview/images/messaging_style.png" /></p>
-<p><b>Figure 3</b>. The expanded notification includes contextually relevant
- Smart Reply responses below the primary action.
-</p>
<p>Responses generated by Smart Reply are shown in addition to those set using the
<a href="{@docRoot}reference/android/support/v4/app/RemoteInput.Builder.html#setChoices(java.lang.CharSequence[])">{@code setChoices()}</a> method.
@@ -189,7 +194,7 @@
<ol>
<li>Use <a href="{@docRoot}preview/features/notification-updates.html#style">{@code Notification.MessagingStyle}</a>.
</li>
- <li>Call the method
+ <li>Call the method
<a href="{@docRoot}wear/preview/start.html#get_the_preview_reference_documentation">{@code setAllowGeneratedReplies()}</a>
for the notification action.</li>
<li>Ensure that the notification action has a
@@ -222,8 +227,9 @@
.setSmallIcon(R.drawable.new_message)
.setLargeIcon(aBitmap)
// 2) set the style to MessagingStyle
- .setStyle(new NotificationCompat.MessagingStyle(resources.getString(R.string.reply_name)).addMessage(messages[0].getText(), messages[0].getTime(), messages[0].getSender())
- .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getSender()))
+ .setStyle(new NotificationCompat.MessagingStyle(resources.getString(R.string.reply_name))
+ .addMessage(messages[0].getText(), messages[0].getTime(), messages[0].getSender())
+ .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getSender()))
// 3) add an action with RemoteInput
diff --git a/docs/html/wear/preview/images/comparison_diagram.png b/docs/html/wear/preview/images/comparison_diagram.png
index 7dbf65f2..4bcf10e 100644
--- a/docs/html/wear/preview/images/comparison_diagram.png
+++ b/docs/html/wear/preview/images/comparison_diagram.png
Binary files differ
diff --git a/docs/html/wear/preview/images/messaging_style.png b/docs/html/wear/preview/images/messaging_style.png
index 966e524..a3bf109 100644
--- a/docs/html/wear/preview/images/messaging_style.png
+++ b/docs/html/wear/preview/images/messaging_style.png
Binary files differ
diff --git a/docs/html/wear/preview/images/messaging_style_diagram.png b/docs/html/wear/preview/images/messaging_style_diagram.png
deleted file mode 100644
index 3b21c7973..0000000
--- a/docs/html/wear/preview/images/messaging_style_diagram.png
+++ /dev/null
Binary files differ
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 59c1065..8b3f172 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -805,27 +805,21 @@
// Note that we don't use op->paint in this function - it's never set on a LayerOp
OffscreenBuffer* buffer = *op.layerHandle;
- if (CC_UNLIKELY(!buffer)) {
- // Layer was not allocated, which can occur if there were no draw ops inside. We draw the
- // equivalent by drawing a rect with the same layer properties (alpha/xfer/filter).
- int color = SkColorSetA(SK_ColorTRANSPARENT, op.alpha * 255);
- renderRectForLayer(renderer, op, state,
- color, op.mode, op.colorFilter);
- } else {
- float layerAlpha = op.alpha * state.alpha;
- Glop glop;
- GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(state.roundRectClipState)
- .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount)
- .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap)
- .setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
- Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
- .build();
- renderer.renderGlop(state, glop);
- }
+ if (CC_UNLIKELY(!buffer)) return;
- if (buffer && !buffer->hasRenderedSinceRepaint) {
+ float layerAlpha = op.alpha * state.alpha;
+ Glop glop;
+ GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
+ .setRoundRectClipState(state.roundRectClipState)
+ .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount)
+ .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap)
+ .setTransform(state.computedState.transform, TransformFlags::None)
+ .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
+ Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
+ .build();
+ renderer.renderGlop(state, glop);
+
+ if (!buffer->hasRenderedSinceRepaint) {
buffer->hasRenderedSinceRepaint = true;
if (CC_UNLIKELY(Properties::debugLayersUpdates)) {
// render debug layer highlight
diff --git a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
index 01d3d70..6b7b721 100644
--- a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
@@ -53,7 +53,7 @@
typedef void (*TestBakedOpReceiver)(BakedOpRenderer&, const BakedOpState&);
static void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, RecordedOp* op,
- std::function<void(const Glop& glop)> glopVerifier) {
+ std::function<void(const Glop& glop)> glopVerifier, int expectedGlopCount = 1) {
// Create op, and wrap with basic state.
LinearAllocator allocator;
auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 100));
@@ -61,8 +61,8 @@
ASSERT_NE(nullptr, state);
int glopCount = 0;
- auto glopReceiver = [&glopVerifier, &glopCount] (const Glop& glop) {
- ASSERT_EQ(glopCount++, 0) << "Only one Glop expected";
+ auto glopReceiver = [&glopVerifier, &glopCount, &expectedGlopCount] (const Glop& glop) {
+ ASSERT_LE(glopCount++, expectedGlopCount) << expectedGlopCount << "glop(s) expected";
glopVerifier(glop);
};
ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver);
@@ -75,7 +75,8 @@
static TestBakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X);
#undef X
unmergedReceivers[op->opId](renderer, *state);
- ASSERT_EQ(1, glopCount) << "Exactly one Glop expected";
+ ASSERT_EQ(expectedGlopCount, glopCount) << "Exactly " << expectedGlopCount
+ << "Glop(s) expected";
}
RENDERTHREAD_TEST(BakedOpDispatcher, pathTexture_positionOvalArc) {
@@ -119,12 +120,8 @@
OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case
LayerOp op(Rect(10, 10), Matrix4::identity(), nullptr, &layerPaint, &buffer);
testUnmergedGlopDispatch(renderThread, &op, [&renderThread] (const Glop& glop) {
- // rect glop is dispatched with paint props applied
- EXPECT_EQ(renderThread.renderState().meshState().getUnitQuadVBO(),
- glop.mesh.vertices.bufferObject) << "Unit quad should be drawn";
- EXPECT_EQ(nullptr, glop.fill.texture.texture) << "Should be no texture when layer is null";
- EXPECT_FLOAT_EQ(128 / 255.0f, glop.fill.color.a) << "Rect quad should use op alpha";
- });
+ ADD_FAILURE() << "Nothing should happen";
+ }, 0);
}
static int getGlopTransformFlags(renderthread::RenderThread& renderThread, RecordedOp* op) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 57c14e9..b82f8dd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -86,17 +86,26 @@
if (mState.restored) {
if (DEBUG) Log.d(TAG, "Stack already resolved for uri: " + intent.getData());
} else if (!mState.stack.isEmpty()) {
- // If a non-empty stack is present in our state it was read (presumably)
+ // If a non-empty stack is present in our state, it was read (presumably)
// from EXTRA_STACK intent extra. In this case, we'll skip other means of
- // loading or restoring the stack.
+ // loading or restoring the stack (like URI).
//
- // When restoring from a stack, if a URI is present, it should only ever
- // be a launch URI, or a fake Uri from notifications.
- // Launch URIs support sensible activity management, but don't specify a real
- // content target.
- if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
- assert(uri == null || uri.getAuthority() == null ||
- LauncherActivity.isLaunchUri(uri));
+ // When restoring from a stack, if a URI is present, it should only ever be:
+ // -- a launch URI: Launch URIs support sensible activity management,
+ // but don't specify a real content target)
+ // -- a fake Uri from notifications. These URIs have no authority (TODO: details).
+ //
+ // Any other URI is *sorta* unexpected...except when browsing an archive
+ // in downloads.
+ if(uri != null
+ && uri.getAuthority() != null
+ && !uri.equals(mState.stack.peek())
+ && !LauncherActivity.isLaunchUri(uri)) {
+ if (DEBUG) Log.w(TAG,
+ "Launching with non-empty stack. Ignoring unexpected uri: " + uri);
+ } else {
+ if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
+ }
refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
assert(uri != null);
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2758551..f7a169c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -594,6 +594,12 @@
<!-- The overflow indicator shown when a group has more notification inside the group than the visible ones. An example is "+ 3" [CHAR LIMIT=5] -->
<string name="notification_group_overflow_indicator">+ <xliff:g id="number" example="3">%s</xliff:g></string>
+ <!-- Content description describing how many more notifications are in a group [CHAR LIMIT=NONE] -->
+ <plurals name="notification_group_overflow_description">
+ <item quantity="one"><xliff:g id="number" example="1">%s</xliff:g> more notification inside.</item>
+ <item quantity="other"><xliff:g id="number" example="3">%s</xliff:g> more notifications inside.</item>
+ </plurals>
+
<!-- Content description of button in notification inspector for system settings relating to
notifications from this application [CHAR LIMIT=NONE] -->
<string name="status_bar_notification_inspect_item_title">Notification settings</string>
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index d09587b..998f50f 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -1064,6 +1064,14 @@
int position = DockedDividerUtils.calculatePositionForBounds(event.initialRect,
mDockSide, mDividerSize);
mEntranceAnimationRunning = true;
+
+ // Insets might not have been fetched yet, so fetch manually if needed.
+ if (mStableInsets.isEmpty()) {
+ SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
+ mSnapAlgorithm = null;
+ initializeSnapAlgorithm();
+ }
+
resizeStack(position, mSnapAlgorithm.getMiddleTarget().position,
mSnapAlgorithm.getMiddleTarget());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 6e9e830..b855b7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -18,10 +18,9 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
@@ -181,6 +180,7 @@
return object.getTranslation();
}
};
+ private OnClickListener mOnClickListener;
public boolean isGroupExpansionChanging() {
if (isChildInGroup()) {
@@ -382,6 +382,7 @@
mNotificationParent = childInGroup ? parent : null;
mPrivateLayout.setIsChildInGroup(childInGroup);
updateBackgroundForGroupState();
+ updateClickAndFocus();
if (mNotificationParent != null) {
mNotificationParent.updateBackgroundForGroupState();
}
@@ -593,6 +594,24 @@
mOnExpandClickListener = onExpandClickListener;
}
+ @Override
+ public void setOnClickListener(@Nullable OnClickListener l) {
+ super.setOnClickListener(l);
+ mOnClickListener = l;
+ updateClickAndFocus();
+ }
+
+ private void updateClickAndFocus() {
+ boolean normalChild = !isChildInGroup() || isGroupExpanded();
+ boolean clickable = mOnClickListener != null && normalChild;
+ if (isFocusable() != normalChild) {
+ setFocusable(normalChild);
+ }
+ if (isClickable() != clickable) {
+ setClickable(clickable);
+ }
+ }
+
public void setHeadsUpManager(HeadsUpManager headsUpManager) {
mHeadsUpManager = headsUpManager;
}
@@ -1315,6 +1334,7 @@
if (mChildrenContainer != null) {
mChildrenContainer.setChildrenExpanded(expanded);
}
+ updateClickAndFocus();
}
public static void applyTint(View v, int color) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java
index 8f2c81f..7373607 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java
@@ -112,6 +112,10 @@
if (!text.equals(reusableView.getText())) {
reusableView.setText(text);
}
+ String contentDescription = String.format(mContext.getResources().getQuantityString(
+ R.plurals.notification_group_overflow_description, number), number);
+
+ reusableView.setContentDescription(contentDescription);
return reusableView;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index a0f1bc2..ba191cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -670,6 +670,11 @@
if (mNotificationHeader != null) {
mNotificationHeader.setExpanded(childrenExpanded);
}
+ final int count = mChildren.size();
+ for (int childIdx = 0; childIdx < count; childIdx++) {
+ ExpandableNotificationRow child = mChildren.get(childIdx);
+ child.setChildrenExpanded(childrenExpanded, false);
+ }
}
public void setNotificationParent(ExpandableNotificationRow parent) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 6a8c8b0..dcd9b0c 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2201,11 +2201,11 @@
// If the app is null, then it was probably removed because the process died,
// otherwise wtf
if (r.app != null) {
- Slog.wtfStack(TAG, "Service done with onDestroy, but not inDestroying: "
+ Slog.w(TAG, "Service done with onDestroy, but not inDestroying: "
+ r + ", app=" + r.app);
}
} else if (r.executeNesting != 1) {
- Slog.wtfStack(TAG, "Service done with onDestroy, but executeNesting="
+ Slog.w(TAG, "Service done with onDestroy, but executeNesting="
+ r.executeNesting + ": " + r);
// Fake it to keep from ANR due to orphaned entry.
r.executeNesting = 1;
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 4fd1350..31528e5 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -223,10 +223,11 @@
* stop executing.
*/
JobStatus getRunningJob() {
+ final JobStatus job;
synchronized (mLock) {
- return mRunningJob == null ?
- null : new JobStatus(mRunningJob);
+ job = mRunningJob;
}
+ return job == null ? null : new JobStatus(job);
}
/** Called externally when a job that was scheduled for execution should be cancelled. */
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b5a8bf3..a8b1a4a 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2582,6 +2582,9 @@
}
if (notification.actions != null) {
for (Notification.Action action: notification.actions) {
+ if (action.actionIntent == null) {
+ continue;
+ }
am.setPendingIntentWhitelistDuration(action.actionIntent.getTarget(), duration);
setPendingIntentWhitelistDuration(am, duration, action.getExtras());
final RemoteInput[] remoteInputs = action.getRemoteInputs();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a2bdde4..eb4d755 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2395,6 +2395,10 @@
mPromoteSystemApps =
mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
+ // When upgrading from pre-N, we need to handle package extraction like first boot,
+ // as there is no profiling data available.
+ mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
+
// save off the names of pre-existing system packages prior to scanning; we don't
// want to automatically grant runtime permissions for new system apps
if (mPromoteSystemApps) {
@@ -2407,11 +2411,6 @@
}
}
- // When upgrading from pre-N, we need to handle package extraction like first boot,
- // as there is no profiling data available.
- mIsPreNUpgrade = !mSettings.isNWorkDone();
- mSettings.setNWorkDone();
-
// Collect vendor overlay packages.
// (Do this before scanning any apps.)
// For security and version matching reason, only consider
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 75bd35c..dfd6dfe 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -191,7 +191,6 @@
private static final String TAG_DEFAULT_BROWSER = "default-browser";
private static final String TAG_DEFAULT_DIALER = "default-dialer";
private static final String TAG_VERSION = "version";
- private static final String TAG_N_WORK = "n-work";
private static final String ATTR_NAME = "name";
private static final String ATTR_USER = "user";
@@ -398,17 +397,6 @@
public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
- /**
- * Used to track whether N+ work has been done. This is similar to the file-system level
- * and denotes that first-boot or upgrade-to-N work has been done.
- *
- * Note: the flag has been added to a) allow tracking while an API level check is impossible
- * and b) to merge upgrade as well as first boot (because the flag is false, by default).
- *
- * STOPSHIP: b/27872764
- */
- private boolean mIsNWorkDone = false;
-
Settings(Object lock) {
this(Environment.getDataDirectory(), lock);
}
@@ -2396,10 +2384,6 @@
mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
- serializer.startTag(null, TAG_N_WORK);
- serializer.attribute(null, ATTR_DONE, Boolean.toString(mIsNWorkDone));
- serializer.endTag(null, TAG_N_WORK);
-
serializer.endTag(null, "packages");
serializer.endDocument();
@@ -2937,8 +2921,6 @@
ver.sdkVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION);
ver.databaseVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION);
ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
- } else if (TAG_N_WORK.equals(tagName)) {
- mIsNWorkDone = XmlUtils.readBooleanAttribute(parser, ATTR_DONE, false);
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
+ parser.getName());
@@ -4233,14 +4215,6 @@
return res;
}
- public boolean isNWorkDone() {
- return mIsNWorkDone;
- }
-
- void setNWorkDone() {
- mIsNWorkDone = true;
- }
-
static void printFlags(PrintWriter pw, int val, Object[] spec) {
pw.print("[ ");
for (int i=0; i<spec.length; i+=2) {