diff options
| author | 2017-07-19 23:41:44 +0000 | |
|---|---|---|
| committer | 2017-07-19 23:41:44 +0000 | |
| commit | 8ffa981686dbf0f118ba14946811d33004f00f4c (patch) | |
| tree | 2d21303259ab850a8da44a8eccf2a6869c9da44f | |
| parent | b0bf1d479f3b3b052f62cb30403e5b6f5457a6e9 (diff) | |
| parent | 15733d1f8592de90823012570fd8db4fd3408f14 (diff) | |
Merge "Reducing bitmap sizes in notifications" into oc-dr1-dev
| -rw-r--r-- | core/java/android/app/Notification.java | 85 | ||||
| -rw-r--r-- | core/java/android/app/NotificationManager.java | 1 | ||||
| -rw-r--r-- | core/java/android/widget/RemoteViews.java | 16 | ||||
| -rw-r--r-- | core/res/res/layout/notification_template_right_icon.xml | 4 | ||||
| -rw-r--r-- | core/res/res/values/dimens.xml | 15 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 8 | ||||
| -rw-r--r-- | graphics/java/android/graphics/drawable/Icon.java | 37 |
7 files changed, 164 insertions, 2 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 46e597aada56..d59e99321e5b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -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; @@ -1090,6 +1091,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. * * This is for use when rendering the notification on an audio-focused interface; @@ -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) { @@ -5135,6 +5145,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 */ private boolean isForegroundService() { @@ -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) { + } } /** @@ -5533,6 +5597,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 + */ public RemoteViews makeBigContentView() { // Replace mN.mLargeIcon with mBigLargeIcon if mBigLargeIconSet // This covers the following cases: diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 235b8d445b1c..3a7f61a91a6d 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -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, diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 7761dcafab0a..6e6235192cc9 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -199,6 +199,22 @@ public class RemoteViews implements Parcelable, Filter { } /** + * 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! */ static class MutablePair<F, S> { diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml index fbf75387b786..d379256f7753 100644 --- a/core/res/res/layout/notification_template_right_icon.xml +++ b/core/res/res/layout/notification_template_right_icon.xml @@ -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" diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 9f9c883fe6aa..743f4ad9efeb 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -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> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 58c653b3e5a6..9a7cab4cb6b7 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -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" /> diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index aa38f31d66a1..c329918afc27 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -805,6 +805,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} * is finished and your Drawable is ready. |