Merge "Fixing the colorization of legacy media notifications" into oc-dev

This commit is contained in:
Selim Cinek
2017-05-12 18:35:18 +00:00
committed by Android (Google) Code Review
5 changed files with 168 additions and 23 deletions

View File

@@ -2703,6 +2703,7 @@ public class Notification implements Parcelable
private int mBackgroundColor = COLOR_INVALID;
private int mForegroundColor = COLOR_INVALID;
private int mBackgroundColorHint = COLOR_INVALID;
private boolean mRebuildStyledRemoteViews;
/**
* Constructs a new Builder with the defaults:
@@ -4251,7 +4252,7 @@ public class Notification implements Parcelable
* @hide
*/
public RemoteViews createContentView(boolean increasedHeight) {
if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) {
if (mN.contentView != null && useExistingRemoteView()) {
return mN.contentView;
} else if (mStyle != null) {
final RemoteViews styleView = mStyle.makeContentView(increasedHeight);
@@ -4262,13 +4263,17 @@ public class Notification implements Parcelable
return applyStandardTemplate(getBaseLayoutResource());
}
private boolean useExistingRemoteView() {
return mStyle == null || (!mStyle.displayCustomViewInline()
&& !mRebuildStyledRemoteViews);
}
/**
* Construct a RemoteViews for the final big notification layout.
*/
public RemoteViews createBigContentView() {
RemoteViews result = null;
if (mN.bigContentView != null
&& (mStyle == null || !mStyle.displayCustomViewInline())) {
if (mN.bigContentView != null && useExistingRemoteView()) {
return mN.bigContentView;
} else if (mStyle != null) {
result = mStyle.makeBigContentView();
@@ -4343,8 +4348,7 @@ public class Notification implements Parcelable
* @hide
*/
public RemoteViews createHeadsUpContentView(boolean increasedHeight) {
if (mN.headsUpContentView != null
&& (mStyle == null || !mStyle.displayCustomViewInline())) {
if (mN.headsUpContentView != null && useExistingRemoteView()) {
return mN.headsUpContentView;
} else if (mStyle != null) {
final RemoteViews styleView = mStyle.makeHeadsUpContentView(increasedHeight);
@@ -4806,7 +4810,7 @@ public class Notification implements Parcelable
}
if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
&& (mStyle == null || !mStyle.displayCustomViewInline())) {
&& (useExistingRemoteView())) {
if (mN.contentView == null) {
mN.contentView = createContentView();
mN.extras.putInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT,
@@ -4978,6 +4982,19 @@ public class Notification implements Parcelable
public void setBackgroundColorHint(int backgroundColor) {
mBackgroundColorHint = backgroundColor;
}
/**
* Forces all styled remoteViews to be built from scratch and not use any cached
* RemoteViews.
* This is needed for legacy apps that are baking in their remoteviews into the
* notification.
*
* @hide
*/
public void setRebuildStyledRemoteViews(boolean rebuild) {
mRebuildStyledRemoteViews = rebuild;
}
}
/**

View File

@@ -23,6 +23,7 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.support.annotation.VisibleForTesting;
import android.support.v4.graphics.ColorUtils;
import android.support.v7.graphics.Palette;
import android.util.LayoutDirection;
@@ -57,9 +58,15 @@ public class MediaNotificationProcessor {
private boolean mIsLowPriority;
public MediaNotificationProcessor(Context context, Context packageContext) {
this(context, packageContext, new ImageGradientColorizer());
}
@VisibleForTesting
MediaNotificationProcessor(Context context, Context packageContext,
ImageGradientColorizer colorizer) {
mContext = context;
mPackageContext = packageContext;
mColorizer = new ImageGradientColorizer();
mColorizer = colorizer;
}
/**
@@ -74,6 +81,9 @@ public class MediaNotificationProcessor {
Bitmap bitmap = null;
Drawable drawable = null;
if (largeIcon != null) {
// We're transforming the builder, let's make sure all baked in RemoteViews are
// rebuilt!
builder.setRebuildStyledRemoteViews(true);
drawable = largeIcon.loadDrawable(mPackageContext);
int backgroundColor = 0;
if (notification.isColorizedMedia()) {

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.statusbar.notification;
import static org.junit.Assert.assertNotSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import android.app.Notification;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.widget.RemoteViews;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class MediaNotificationProcessorTest extends SysuiTestCase {
private MediaNotificationProcessor mProcessor;
private Bitmap mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
private ImageGradientColorizer mColorizer;
@Before
public void setUp() {
mColorizer = spy(new TestableColorizer(mBitmap));
mProcessor = new MediaNotificationProcessor(getContext(), getContext(), mColorizer);
}
@Test
public void testColorizedWithLargeIcon() {
Notification.Builder builder = new Notification.Builder(getContext()).setSmallIcon(
R.drawable.ic_person)
.setContentTitle("Title")
.setLargeIcon(mBitmap)
.setContentText("Text");
Notification notification = builder.build();
mProcessor.processNotification(notification, builder);
verify(mColorizer).colorize(any(), anyInt(), anyBoolean());
}
@Test
public void testNotColorizedWithoutLargeIcon() {
Notification.Builder builder = new Notification.Builder(getContext()).setSmallIcon(
R.drawable.ic_person)
.setContentTitle("Title")
.setContentText("Text");
Notification notification = builder.build();
mProcessor.processNotification(notification, builder);
verifyZeroInteractions(mColorizer);
}
@Test
public void testRemoteViewsReset() {
Notification.Builder builder = new Notification.Builder(getContext()).setSmallIcon(
R.drawable.ic_person)
.setContentTitle("Title")
.setStyle(new Notification.MediaStyle())
.setLargeIcon(mBitmap)
.setContentText("Text");
Notification notification = builder.build();
RemoteViews remoteViews = new RemoteViews(getContext().getPackageName(),
R.layout.custom_view_dark);
notification.contentView = remoteViews;
notification.bigContentView = remoteViews;
notification.headsUpContentView = remoteViews;
mProcessor.processNotification(notification, builder);
verify(mColorizer).colorize(any(), anyInt(), anyBoolean());
RemoteViews contentView = builder.createContentView();
assertNotSame(contentView, remoteViews);
contentView = builder.createBigContentView();
assertNotSame(contentView, remoteViews);
contentView = builder.createHeadsUpContentView();
assertNotSame(contentView, remoteViews);
}
public static class TestableColorizer extends ImageGradientColorizer {
private final Bitmap mBitmap;
private TestableColorizer(Bitmap bitmap) {
mBitmap = bitmap;
}
@Override
public Bitmap colorize(Drawable drawable, int backgroundColor, boolean isRtl) {
return mBitmap;
}
}
}

View File

@@ -1,18 +1,20 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2017 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
* 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.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.notification;
package com.android.systemui.statusbar.notification;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

View File

@@ -1,18 +1,20 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2017 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
* 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.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.notification;
package com.android.systemui.statusbar.notification;
import android.service.notification.StatusBarNotification;
import android.support.test.runner.AndroidJUnit4;