Merge "Reducing bitmap sizes in notifications" into oc-dr1-dev

This commit is contained in:
Selim Cinek
2017-07-19 23:41:44 +00:00
committed by Android (Google) Code Review
7 changed files with 164 additions and 2 deletions

View File

@@ -33,6 +33,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ShortcutInfo;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -1089,6 +1090,11 @@ public class Notification implements Parcelable
*/
public static final String EXTRA_CONTAINS_CUSTOM_VIEW = "android.contains.customView";
/**
* @hide
*/
public static final String EXTRA_REDUCED_IMAGES = "android.reduced.images";
/**
* {@link #extras} key: the audio contents of this notification.
*
@@ -4943,9 +4949,13 @@ public class Notification implements Parcelable
buildUnstyled();
if (mStyle != null) {
mStyle.reduceImageSizes(mContext);
mStyle.purgeResources();
mStyle.buildStyled(mN);
}
mN.reduceImageSizes(mContext);
if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
&& (useExistingRemoteView())) {
if (mN.contentView == null) {
@@ -5134,6 +5144,52 @@ public class Notification implements Parcelable
}
}
/**
* Reduces the image sizes to conform to a maximum allowed size. This also processes all custom
* remote views.
*
* @hide
*/
void reduceImageSizes(Context context) {
if (extras.getBoolean(EXTRA_REDUCED_IMAGES)) {
return;
}
if (mLargeIcon != null || largeIcon != null) {
Resources resources = context.getResources();
Class<? extends Style> style = getNotificationStyle();
int maxWidth = resources.getDimensionPixelSize(R.dimen.notification_right_icon_size);
int maxHeight = maxWidth;
if (MediaStyle.class.equals(style)
|| DecoratedMediaCustomViewStyle.class.equals(style)) {
maxHeight = resources.getDimensionPixelSize(
R.dimen.notification_media_image_max_height);
maxWidth = resources.getDimensionPixelSize(
R.dimen.notification_media_image_max_width);
}
if (mLargeIcon != null) {
mLargeIcon.scaleDownIfNecessary(maxWidth, maxHeight);
}
if (largeIcon != null) {
largeIcon = Icon.scaleDownIfNecessary(largeIcon, maxWidth, maxHeight);
}
}
reduceImageSizesForRemoteView(contentView, context);
reduceImageSizesForRemoteView(headsUpContentView, context);
reduceImageSizesForRemoteView(bigContentView, context);
extras.putBoolean(EXTRA_REDUCED_IMAGES, true);
}
private void reduceImageSizesForRemoteView(RemoteViews remoteView, Context context) {
if (remoteView != null) {
Resources resources = context.getResources();
int maxWidth = resources.getDimensionPixelSize(
R.dimen.notification_custom_view_max_image_width);
int maxHeight = resources.getDimensionPixelSize(
R.dimen.notification_custom_view_max_image_height);
remoteView.reduceImageSizes(maxWidth, maxHeight);
}
}
/**
* @return whether this notification is a foreground service notification
*/
@@ -5435,6 +5491,14 @@ public class Notification implements Parcelable
public boolean displayCustomViewInline() {
return false;
}
/**
* Reduces the image sizes contained in this style.
*
* @hide
*/
public void reduceImageSizes(Context context) {
}
}
/**
@@ -5530,6 +5594,27 @@ public class Notification implements Parcelable
}
}
/**
* @hide
*/
@Override
public void reduceImageSizes(Context context) {
super.reduceImageSizes(context);
Resources resources = context.getResources();
if (mPicture != null) {
int maxPictureWidth = resources.getDimensionPixelSize(
R.dimen.notification_big_picture_max_height);
int maxPictureHeight = resources.getDimensionPixelSize(
R.dimen.notification_big_picture_max_width);
mPicture = Icon.scaleDownIfNecessary(mPicture, maxPictureWidth, maxPictureHeight);
}
if (mBigLargeIcon != null) {
int rightIconSize = resources.getDimensionPixelSize(
R.dimen.notification_right_icon_size);
mBigLargeIcon.scaleDownIfNecessary(rightIconSize, rightIconSize);
}
}
/**
* @hide
*/

View File

@@ -312,6 +312,7 @@ public class NotificationManager {
}
}
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
notification.reduceImageSizes(mContext);
final Notification copy = Builder.maybeCloneStrippedForDelivery(notification);
try {
service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,

View File

@@ -198,6 +198,22 @@ public class RemoteViews implements Parcelable, Filter {
mActions.add(new SetRemoteInputsAction(viewId, remoteInputs));
}
/**
* Reduces all images and ensures that they are all below the given sizes.
*
* @param maxWidth the maximum width allowed
* @param maxHeight the maximum height allowed
*
* @hide
*/
public void reduceImageSizes(int maxWidth, int maxHeight) {
ArrayList<Bitmap> cache = mBitmapCache.mBitmaps;
for (int i = 0; i < cache.size(); i++) {
Bitmap bitmap = cache.get(i);
cache.set(i, Icon.scaleDownIfNecessary(bitmap, maxWidth, maxHeight));
}
}
/**
* Handle with care!
*/

View File

@@ -21,8 +21,8 @@
android:layout_height="wrap_content"
android:layout_gravity="top|end">
<ImageView android:id="@+id/right_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_width="@dimen/notification_right_icon_size"
android:layout_height="@dimen/notification_right_icon_size"
android:layout_gravity="top|end"
android:layout_marginTop="36dp"
android:layout_marginEnd="@dimen/notification_content_margin_end"

View File

@@ -580,6 +580,21 @@
<dimen name="item_touch_helper_swipe_escape_velocity">120dp</dimen>
<dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen>
<!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. This value is determined by the maximum notification height -->
<dimen name="notification_custom_view_max_image_height">284dp</dimen>
<!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. This value is determined a maximum notification width -->
<dimen name="notification_custom_view_max_image_width">450dp</dimen>
<!-- The maximum height of a big picture in a notification. The images will be reduced to that height in case they are bigger. This value is determined by the maximum notification height -->
<dimen name="notification_big_picture_max_height">284dp</dimen>
<!-- The maximum width of a big picture in a notification. The images will be reduced to that width in case they are bigger. This value is determined by the standard panel size -->
<dimen name="notification_big_picture_max_width">416dp</dimen>
<!-- The maximum height of a image in a media notification. The images will be reduced to that height in case they are bigger. This value is determined by the expanded media template-->
<dimen name="notification_media_image_max_height">140dp</dimen>
<!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.-->
<dimen name="notification_media_image_max_width">280dp</dimen>
<!-- The size of the right icon -->
<dimen name="notification_right_icon_size">40dp</dimen>
<!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
<dimen name="autofill_dataset_picker_max_size">90%</dimen>

View File

@@ -2946,6 +2946,14 @@
<java-symbol type="style" name="AutofillDatasetPicker" />
<java-symbol type="dimen" name="autofill_dataset_picker_max_size"/>
<java-symbol type="dimen" name="notification_big_picture_max_height"/>
<java-symbol type="dimen" name="notification_big_picture_max_width"/>
<java-symbol type="dimen" name="notification_media_image_max_width"/>
<java-symbol type="dimen" name="notification_media_image_max_height"/>
<java-symbol type="dimen" name="notification_right_icon_size"/>
<java-symbol type="dimen" name="notification_custom_view_max_image_height"/>
<java-symbol type="dimen" name="notification_custom_view_max_image_width"/>
<!-- Accessibility fingerprint gestures -->
<java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
<java-symbol type="string" name="capability_desc_canCaptureFingerprintGestures" />

View File

@@ -804,6 +804,43 @@ public final class Icon implements Parcelable {
}
};
/**
* Scale down a bitmap to a given max width and max height. The scaling will be done in a uniform way
* @param bitmap the bitmap to scale down
* @param maxWidth the maximum width allowed
* @param maxHeight the maximum height allowed
*
* @return the scaled bitmap if necessary or the original bitmap if no scaling was needed
* @hide
*/
public static Bitmap scaleDownIfNecessary(Bitmap bitmap, int maxWidth, int maxHeight) {
int bitmapWidth = bitmap.getWidth();
int bitmapHeight = bitmap.getHeight();
if (bitmapWidth > maxWidth || bitmapHeight > maxHeight) {
float scale = Math.min((float) maxWidth / bitmapWidth,
(float) maxHeight / bitmapHeight);
bitmap = Bitmap.createScaledBitmap(bitmap, (int) (scale * bitmapWidth),
(int) (scale * bitmapHeight), true /* filter */);
}
return bitmap;
}
/**
* Scale down this icon to a given max width and max height.
* The scaling will be done in a uniform way and currently only bitmaps are supported.
* @param maxWidth the maximum width allowed
* @param maxHeight the maximum height allowed
*
* @hide
*/
public void scaleDownIfNecessary(int maxWidth, int maxHeight) {
if (mType != TYPE_BITMAP && mType != TYPE_ADAPTIVE_BITMAP) {
return;
}
Bitmap bitmap = getBitmap();
setBitmap(scaleDownIfNecessary(bitmap, maxWidth, maxHeight));
}
/**
* Implement this interface to receive a callback when
* {@link #loadDrawableAsync(Context, OnDrawableLoadedListener, Handler) loadDrawableAsync}