Merge "Fixed a bug with decorated custom views" into oc-mr1-dev

This commit is contained in:
TreeHugger Robot
2017-08-22 22:48:14 +00:00
committed by Android (Google) Code Review
4 changed files with 62 additions and 13 deletions

View File

@@ -6951,6 +6951,7 @@ public class Notification implements Parcelable
customContent = customContent.clone();
remoteViews.removeAllViewsExceptId(R.id.notification_main_column, R.id.progress);
remoteViews.addView(R.id.notification_main_column, customContent, 0 /* index */);
remoteViews.setReapplyDisallowed();
}
// also update the end margin if there is an image
int endMargin = R.dimen.notification_content_margin_end;
@@ -7057,6 +7058,7 @@ public class Notification implements Parcelable
customContent = customContent.clone();
remoteViews.removeAllViews(id);
remoteViews.addView(id, customContent);
remoteViews.setReapplyDisallowed();
}
return remoteViews;
}

View File

@@ -153,6 +153,12 @@ public class RemoteViews implements Parcelable, Filter {
*/
private boolean mIsRoot = true;
/**
* Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify
* the layout in a way that isn't recoverable, since views are being removed.
*/
private boolean mReapplyDisallowed;
/**
* Constants to whether or not this RemoteViews is composed of a landscape and portrait
* RemoteViews.
@@ -214,6 +220,26 @@ public class RemoteViews implements Parcelable, Filter {
}
}
/**
* Set that it is disallowed to reapply another remoteview with the same layout as this view.
* This should be done if an action is destroying the view tree of the base layout.
*
* @hide
*/
public void setReapplyDisallowed() {
mReapplyDisallowed = true;
}
/**
* @return Whether it is disallowed to reapply another remoteview with the same layout as this
* view. True if this remoteview has actions that destroyed view tree of the base layout.
*
* @hide
*/
public boolean isReapplyDisallowed() {
return mReapplyDisallowed;
}
/**
* Handle with care!
*/
@@ -2429,6 +2455,7 @@ public class RemoteViews implements Parcelable, Filter {
mApplication = mPortrait.mApplication;
mLayoutId = mPortrait.getLayoutId();
}
mReapplyDisallowed = parcel.readInt() == 0;
// setup the memory usage statistics
mMemoryUsageCounter = new MemoryUsageCounter();
@@ -3738,6 +3765,7 @@ public class RemoteViews implements Parcelable, Filter {
// Both RemoteViews already share the same package and user
mPortrait.writeToParcel(dest, flags | PARCELABLE_ELIDE_DUPLICATES);
}
dest.writeInt(mReapplyDisallowed ? 1 : 0);
}
private static ApplicationInfo getApplicationInfo(String packageName, int userId) {

View File

@@ -193,7 +193,7 @@ public class NotificationInflater {
int flag = FLAG_REINFLATE_CONTENT_VIEW;
if ((reInflateFlags & flag) != 0) {
boolean isNewView = !compareRemoteViews(result.newContentView, entry.cachedContentView);
boolean isNewView = !canReapplyRemoteView(result.newContentView, entry.cachedContentView);
ApplyCallback applyCallback = new ApplyCallback() {
@Override
public void setResultView(View v) {
@@ -215,7 +215,7 @@ public class NotificationInflater {
flag = FLAG_REINFLATE_EXPANDED_VIEW;
if ((reInflateFlags & flag) != 0) {
if (result.newExpandedView != null) {
boolean isNewView = !compareRemoteViews(result.newExpandedView,
boolean isNewView = !canReapplyRemoteView(result.newExpandedView,
entry.cachedBigContentView);
ApplyCallback applyCallback = new ApplyCallback() {
@Override
@@ -240,7 +240,7 @@ public class NotificationInflater {
flag = FLAG_REINFLATE_HEADS_UP_VIEW;
if ((reInflateFlags & flag) != 0) {
if (result.newHeadsUpView != null) {
boolean isNewView = !compareRemoteViews(result.newHeadsUpView,
boolean isNewView = !canReapplyRemoteView(result.newHeadsUpView,
entry.cachedHeadsUpContentView);
ApplyCallback applyCallback = new ApplyCallback() {
@Override
@@ -264,7 +264,7 @@ public class NotificationInflater {
flag = FLAG_REINFLATE_PUBLIC_VIEW;
if ((reInflateFlags & flag) != 0) {
boolean isNewView = !compareRemoteViews(result.newPublicView,
boolean isNewView = !canReapplyRemoteView(result.newPublicView,
entry.cachedPublicContentView);
ApplyCallback applyCallback = new ApplyCallback() {
@Override
@@ -288,7 +288,7 @@ public class NotificationInflater {
if ((reInflateFlags & flag) != 0) {
NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout;
boolean isNewView = !canReapplyAmbient(row, redactAmbient) ||
!compareRemoteViews(result.newAmbientView, entry.cachedAmbientContentView);
!canReapplyRemoteView(result.newAmbientView, entry.cachedAmbientContentView);
ApplyCallback applyCallback = new ApplyCallback() {
@Override
public void setResultView(View v) {
@@ -486,14 +486,21 @@ public class NotificationInflater {
return builder.createContentView(useLarge);
}
// Returns true if the RemoteViews are the same.
private static boolean compareRemoteViews(final RemoteViews a, final RemoteViews b) {
return (a == null && b == null) ||
(a != null && b != null
&& b.getPackage() != null
&& a.getPackage() != null
&& a.getPackage().equals(b.getPackage())
&& a.getLayoutId() == b.getLayoutId());
/**
* @param newView The new view that will be applied
* @param oldView The old view that was applied to the existing view before
* @return {@code true} if the RemoteViews are the same and the view can be reused to reapply.
*/
@VisibleForTesting
static boolean canReapplyRemoteView(final RemoteViews newView,
final RemoteViews oldView) {
return (newView == null && oldView == null) ||
(newView != null && oldView != null
&& oldView.getPackage() != null
&& newView.getPackage() != null
&& newView.getPackage().equals(oldView.getPackage())
&& newView.getLayoutId() == oldView.getLayoutId()
&& !oldView.isReapplyDisallowed());
}
public void setInflationCallback(InflationCallback callback) {

View File

@@ -199,6 +199,18 @@ public class NotificationInflaterTest extends SysuiTestCase {
runningTask.abort();
}
@Test
public void doesntReapplyDisallowedRemoteView() throws Exception {
mBuilder.setStyle(new Notification.MediaStyle());
RemoteViews mediaView = mBuilder.createContentView();
mBuilder.setStyle(new Notification.DecoratedCustomViewStyle());
mBuilder.setCustomContentView(new RemoteViews(getContext().getPackageName(),
R.layout.custom_view_dark));
RemoteViews decoratedMediaView = mBuilder.createContentView();
Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!",
NotificationInflater.canReapplyRemoteView(mediaView, decoratedMediaView));
}
public static void runThenWaitForInflation(Runnable block,
NotificationInflater inflater) throws Exception {
runThenWaitForInflation(block, false /* expectingException */, inflater);