Increased the collapsed size of messaging notifications
Messaging notifications now get an increased boost in size,
since those are usually important to the user.
Test: existing tests pass
Bug: 34469375
Change-Id: Idfc2d2403b04c4c2d17b821e3ccbbbd48d31654d
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 80f4985..1c9acae 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -48,6 +48,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
import android.text.BidiFormatter;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@@ -3854,10 +3855,24 @@
* 3. Standard template view
*/
public RemoteViews createContentView() {
+ return createContentView(false /* increasedheight */ );
+ }
+
+ /**
+ * Construct a RemoteViews for the smaller content view.
+ *
+ * @param increasedHeight true if this layout be created with an increased height. Some
+ * styles may support showing more then just that basic 1U size
+ * and the system may decide to render important notifications
+ * slightly bigger even when collapsed.
+ *
+ * @hide
+ */
+ public RemoteViews createContentView(boolean increasedHeight) {
if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) {
return mN.contentView;
} else if (mStyle != null) {
- final RemoteViews styleView = mStyle.makeContentView();
+ final RemoteViews styleView = mStyle.makeContentView(increasedHeight);
if (styleView != null) {
return styleView;
}
@@ -4487,6 +4502,19 @@
}
/**
+ * @return the style class of this notification
+ * @hide
+ */
+ public Class<? extends Notification.Style> getNotificationStyle() {
+ String templateClass = extras.getString(Notification.EXTRA_TEMPLATE);
+
+ if (!TextUtils.isEmpty(templateClass)) {
+ return Notification.getNotificationStyleClass(templateClass);
+ }
+ return null;
+ }
+
+ /**
* @return true if this notification is colorized. This also factors in wheather the
* notification is ongoing.
*
@@ -4607,11 +4635,13 @@
}
/**
- * Construct a Style-specific RemoteViews for the final 1U notification layout.
+ * Construct a Style-specific RemoteViews for the collapsed notification layout.
* The default implementation has nothing additional to add.
+ *
+ * @param increasedHeight true if this layout be created with an increased height.
* @hide
*/
- public RemoteViews makeContentView() {
+ public RemoteViews makeContentView(boolean increasedHeight) {
return null;
}
@@ -4957,6 +4987,23 @@
}
/**
+ * @param increasedHeight true if this layout be created with an increased height.
+ *
+ * @hide
+ */
+ @Override
+ public RemoteViews makeContentView(boolean increasedHeight) {
+ if (increasedHeight) {
+ ArrayList<Action> actions = mBuilder.mActions;
+ mBuilder.mActions = new ArrayList<>();
+ RemoteViews remoteViews = makeBigContentView();
+ mBuilder.mActions = actions;
+ return remoteViews;
+ }
+ return super.makeContentView(increasedHeight);
+ }
+
+ /**
* @hide
*/
public RemoteViews makeBigContentView() {
@@ -5220,17 +5267,25 @@
* @hide
*/
@Override
- public RemoteViews makeContentView() {
- Message m = findLatestIncomingMessage();
- CharSequence title = mConversationTitle != null
- ? mConversationTitle
- : (m == null) ? null : m.mSender;
- CharSequence text = (m == null)
- ? null
- : mConversationTitle != null ? makeMessageLine(m, mBuilder) : m.mText;
+ public RemoteViews makeContentView(boolean increasedHeight) {
+ if (!increasedHeight) {
+ Message m = findLatestIncomingMessage();
+ CharSequence title = mConversationTitle != null
+ ? mConversationTitle
+ : (m == null) ? null : m.mSender;
+ CharSequence text = (m == null)
+ ? null
+ : mConversationTitle != null ? makeMessageLine(m, mBuilder) : m.mText;
- return mBuilder.applyStandardTemplateWithActions(mBuilder.getBaseLayoutResource(),
- mBuilder.mParams.reset().hasProgress(false).title(title).text(text));
+ return mBuilder.applyStandardTemplate(mBuilder.getBaseLayoutResource(),
+ mBuilder.mParams.reset().hasProgress(false).title(title).text(text));
+ } else {
+ ArrayList<Action> actions = mBuilder.mActions;
+ mBuilder.mActions = new ArrayList<>();
+ RemoteViews remoteViews = makeBigContentView();
+ mBuilder.mActions = actions;
+ return remoteViews;
+ }
}
private Message findLatestIncomingMessage() {
@@ -5795,7 +5850,7 @@
* @hide
*/
@Override
- public RemoteViews makeContentView() {
+ public RemoteViews makeContentView(boolean increasedHeight) {
return makeMediaContentView();
}
@@ -5971,7 +6026,7 @@
* @hide
*/
@Override
- public RemoteViews makeContentView() {
+ public RemoteViews makeContentView(boolean increasedHeight) {
return makeStandardTemplateWithCustomContent(mBuilder.mN.contentView);
}
@@ -6085,8 +6140,8 @@
* @hide
*/
@Override
- public RemoteViews makeContentView() {
- RemoteViews remoteViews = super.makeContentView();
+ public RemoteViews makeContentView(boolean increasedHeight) {
+ RemoteViews remoteViews = super.makeContentView(false /* increasedHeight */);
return buildIntoRemoteView(remoteViews, R.id.notification_content_container,
mBuilder.mN.contentView);
}
@@ -6108,7 +6163,7 @@
return buildIntoRemoteView(remoteViews, R.id.notification_main_column,
customRemoteView);
} else if (customRemoteView != mBuilder.mN.contentView){
- remoteViews = super.makeContentView();
+ remoteViews = super.makeContentView(false /* increasedHeight */);
return buildIntoRemoteView(remoteViews, R.id.notification_content_container,
customRemoteView);
} else {
diff --git a/core/java/com/android/internal/util/NotificationMessagingUtil.java b/core/java/com/android/internal/util/NotificationMessagingUtil.java
new file mode 100644
index 0000000..518cf41
--- /dev/null
+++ b/core/java/com/android/internal/util/NotificationMessagingUtil.java
@@ -0,0 +1,93 @@
+/*
+ * 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.internal.util;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+
+import java.util.Objects;
+
+/**
+ * A util to look up messaging related functions for notifications. This is used for both the
+ * ranking and the actual layout.
+ */
+public class NotificationMessagingUtil {
+
+ private static final String DEFAULT_SMS_APP_SETTING = Settings.Secure.SMS_DEFAULT_APPLICATION;
+ private final Context mContext;
+ private ArrayMap<Integer, String> mDefaultSmsApp = new ArrayMap<>();
+
+ public NotificationMessagingUtil(Context context) {
+ mContext = context;
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING), false, mSmsContentObserver);
+ }
+
+ @SuppressWarnings("deprecation")
+ private boolean isDefaultMessagingApp(StatusBarNotification sbn) {
+ final int userId = sbn.getUserId();
+ if (userId == UserHandle.USER_NULL || userId == UserHandle.USER_ALL) return false;
+ if (mDefaultSmsApp.get(userId) == null) {
+ cacheDefaultSmsApp(userId);
+ }
+ return Objects.equals(mDefaultSmsApp.get(userId), sbn.getPackageName());
+ }
+
+ private void cacheDefaultSmsApp(int userId) {
+ mDefaultSmsApp.put(userId, Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.SMS_DEFAULT_APPLICATION, userId));
+ }
+
+ private final ContentObserver mSmsContentObserver = new ContentObserver(
+ new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ if (Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING).equals(uri)) {
+ cacheDefaultSmsApp(userId);
+ }
+ }
+ };
+
+ public boolean isImportantMessaging(StatusBarNotification sbn, int importance) {
+ if (importance < NotificationManager.IMPORTANCE_LOW) {
+ return false;
+ }
+
+ Class<? extends Notification.Style> style = sbn.getNotification().getNotificationStyle();
+ if (Notification.MessagingStyle.class.equals(style)) {
+ return true;
+ }
+
+ if (Notification.CATEGORY_MESSAGE.equals(sbn.getNotification().category)
+ && isDefaultMessagingApp(sbn)) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ddcc4ba..cf18373 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -69,6 +69,9 @@
<!-- Height of a small notification in the status bar-->
<dimen name="notification_min_height">92dp</dimen>
+ <!-- Height of a small notification in the status bar if it is a large (like messaging)-->
+ <dimen name="notification_min_height_large">132dp</dimen>
+
<!-- Height of a small notification in the status bar which was used before android N -->
<dimen name="notification_min_height_legacy">64dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index d1245b1..f19d6d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -77,6 +77,7 @@
private int mMaxHeadsUpHeightLegacy;
private int mMaxHeadsUpHeight;
private int mNotificationMinHeight;
+ private int mNotificationMinHeightLarge;
private int mNotificationMaxHeight;
private int mNotificationAmbientHeight;
private int mIncreasedPaddingBetweenElements;
@@ -207,6 +208,7 @@
private Runnable mOnDismissRunnable;
private boolean mIsLowPriority;
private boolean mIsColorized;
+ private boolean mUseIncreasedCollapsedHeight;
@Override
public boolean isGroupExpansionChanging() {
@@ -341,8 +343,14 @@
boolean customView = layout.getContractedChild().getId()
!= com.android.internal.R.id.status_bar_latest_event_content;
boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
- int minHeight = customView && beforeN && !mIsSummaryWithChildren ?
- mNotificationMinHeightLegacy : mNotificationMinHeight;
+ int minHeight;
+ if (customView && beforeN && !mIsSummaryWithChildren) {
+ minHeight = mNotificationMinHeightLegacy;
+ } else if (mUseIncreasedCollapsedHeight && layout == mPrivateLayout) {
+ minHeight = mNotificationMinHeightLarge;
+ } else {
+ minHeight = mNotificationMinHeight;
+ }
boolean headsUpCustom = layout.getHeadsUpChild() != null &&
layout.getHeadsUpChild().getId()
!= com.android.internal.R.id.status_bar_latest_event_content;
@@ -979,6 +987,10 @@
}
}
+ public void setUseIncreasedCollapsedHeight(boolean use) {
+ mUseIncreasedCollapsedHeight = use;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
@@ -992,6 +1004,8 @@
private void initDimens() {
mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy);
mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height);
+ mNotificationMinHeightLarge = getFontScaledHeight(
+ R.dimen.notification_min_height_large);
mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height);
mNotificationAmbientHeight = getFontScaledHeight(R.dimen.notification_ambient_height);
mMaxHeadsUpHeightLegacy = getFontScaledHeight(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index bbfcf31..bb9b070 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -122,13 +122,13 @@
}
public boolean cacheContentViews(Context ctx, Notification updatedNotification,
- boolean isLowPriority) {
+ boolean isLowPriority, boolean useIncreasedCollapsedView) {
boolean applyInPlace = false;
if (updatedNotification != null) {
final Notification.Builder updatedNotificationBuilder
= Notification.Builder.recoverBuilder(ctx, updatedNotification);
final RemoteViews newContentView = createContentView(updatedNotificationBuilder,
- isLowPriority);
+ isLowPriority, useIncreasedCollapsedView);
final RemoteViews newBigContentView = createBigContentView(
updatedNotificationBuilder, isLowPriority);
final RemoteViews newHeadsUpContentView =
@@ -158,7 +158,8 @@
final Notification.Builder builder
= Notification.Builder.recoverBuilder(ctx, notification.getNotification());
- cachedContentView = createContentView(builder, isLowPriority);
+ cachedContentView = createContentView(builder, isLowPriority,
+ useIncreasedCollapsedView);
cachedBigContentView = createBigContentView(builder, isLowPriority);
cachedHeadsUpContentView = builder.createHeadsUpContentView();
cachedPublicContentView = builder.makePublicContentView();
@@ -184,11 +185,11 @@
}
private RemoteViews createContentView(Notification.Builder builder,
- boolean isAmbient) {
- if (isAmbient) {
+ boolean isLowPriority, boolean useLarge) {
+ if (isLowPriority) {
return builder.makeLowPriorityContentView(false /* useRegularSubtext */);
}
- return builder.createContentView();
+ return builder.createContentView(useLarge);
}
// Returns true if the RemoteViews are the same.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 018d888..6ace987 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1,3 +1,5 @@
+
+
/*
* Copyright (C) 2010 The Android Open Source Project
*
@@ -112,6 +114,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.NotificationMessagingUtil;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -701,6 +704,7 @@
}
};
+ private NotificationMessagingUtil mMessagingUtil;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private UserSwitcherController mUserSwitcherController;
private NetworkController mNetworkController;
@@ -763,6 +767,7 @@
Context.DEVICE_POLICY_SERVICE);
mNotificationData = new NotificationData(this);
+ mMessagingUtil = new NotificationMessagingUtil(mContext);
mAccessibilityManager = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -6318,8 +6323,10 @@
final StatusBarNotification sbn = entry.notification;
boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
+ boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(sbn,
+ mNotificationData.getImportance(sbn.getKey()));
try {
- entry.cacheContentViews(mContext, null, isLowPriority);
+ entry.cacheContentViews(mContext, null, isLowPriority, useIncreasedCollapsedHeight);
} catch (RuntimeException e) {
Log.e(TAG, "Unable to get notification remote views", e);
return false;
@@ -6489,6 +6496,7 @@
row.setUserExpanded(userExpanded);
}
row.setUserLocked(userLocked);
+ row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
row.onNotificationUpdated(entry);
return true;
}
@@ -6978,10 +6986,13 @@
Notification n = notification.getNotification();
mNotificationData.updateRanking(ranking);
+ boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(notification,
+ mNotificationData.getImportance(notification.getKey()));
+ entry.row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
boolean applyInPlace;
try {
applyInPlace = entry.cacheContentViews(mContext, notification.getNotification(),
- mNotificationData.isAmbient(key));
+ mNotificationData.isAmbient(key), useIncreasedCollapsedHeight);
} catch (RuntimeException e) {
Log.e(TAG, "Unable to get notification remote views", e);
applyInPlace = false;
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 6f49df4..279bf90 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -31,6 +31,8 @@
import android.text.TextUtils;
import android.util.ArrayMap;
+import com.android.internal.util.NotificationMessagingUtil;
+
import java.util.Comparator;
import java.util.Objects;
@@ -40,18 +42,15 @@
public class NotificationComparator
implements Comparator<NotificationRecord> {
- private final String DEFAULT_SMS_APP_SETTING = Settings.Secure.SMS_DEFAULT_APPLICATION;
-
private final Context mContext;
+ private final NotificationMessagingUtil mMessagingUtil;
private String mDefaultPhoneApp;
- private ArrayMap<Integer, String> mDefaultSmsApp = new ArrayMap<>();
public NotificationComparator(Context context) {
mContext = context;
mContext.registerReceiver(mPhoneAppBroadcastReceiver,
new IntentFilter(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED));
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING), false, mSmsContentObserver);
+ mMessagingUtil = new NotificationMessagingUtil(mContext);
}
@Override
@@ -73,9 +72,15 @@
return -1 * Boolean.compare(leftImportantOngoing, rightImportantOngoing);
}
+ boolean leftMessaging = isImportantMessaging(left);
+ boolean rightMessaging = isImportantMessaging(right);
+ if (leftMessaging != rightMessaging) {
+ return -1 * Boolean.compare(leftMessaging, rightMessaging);
+ }
+
// Next: sufficiently import person to person communication
- boolean leftPeople = isImportantMessaging(left);
- boolean rightPeople = isImportantMessaging(right);
+ boolean leftPeople = isImportantPeople(left);
+ boolean rightPeople = isImportantPeople(right);
if (leftPeople && rightPeople){
// by contact proximity, close to far. if same proximity, check further fields.
@@ -128,50 +133,31 @@
if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
return false;
}
-
// TODO: add whitelist
return isCall(record) || isMediaNotification(record);
}
- protected boolean isImportantMessaging(NotificationRecord record) {
+ protected boolean isImportantPeople(NotificationRecord record) {
if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
return false;
}
-
- Class<? extends Notification.Style> style = getNotificationStyle(record);
- if (Notification.MessagingStyle.class.equals(style)) {
- return true;
- }
-
if (record.getContactAffinity() > ValidateNotificationPeople.NONE) {
return true;
}
-
- if (record.getNotification().category == Notification.CATEGORY_MESSAGE
- && isDefaultMessagingApp(record)) {
- return true;
- }
-
return false;
}
+ protected boolean isImportantMessaging(NotificationRecord record) {
+ return mMessagingUtil.isImportantMessaging(record.sbn, record.getImportance());
+ }
+
private boolean isOngoing(NotificationRecord record) {
final int ongoingFlags =
Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_ONGOING_EVENT;
return (record.getNotification().flags & ongoingFlags) != 0;
}
- private Class<? extends Notification.Style> getNotificationStyle(NotificationRecord record) {
- String templateClass =
- record.getNotification().extras.getString(Notification.EXTRA_TEMPLATE);
-
- if (!TextUtils.isEmpty(templateClass)) {
- return Notification.getNotificationStyleClass(templateClass);
- }
- return null;
- }
-
private boolean isMediaNotification(NotificationRecord record) {
return record.getNotification().extras.getParcelable(
Notification.EXTRA_MEDIA_SESSION) != null;
@@ -191,18 +177,6 @@
return Objects.equals(pkg, mDefaultPhoneApp);
}
- @SuppressWarnings("deprecation")
- private boolean isDefaultMessagingApp(NotificationRecord record) {
- final int userId = record.getUserId();
- if (userId == UserHandle.USER_NULL || userId == UserHandle.USER_ALL) return false;
- if (mDefaultSmsApp.get(userId) == null) {
- mDefaultSmsApp.put(userId, Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.SMS_DEFAULT_APPLICATION, userId));
- }
- return Objects.equals(mDefaultSmsApp.get(userId), record.sbn.getPackageName());
- }
-
private final BroadcastReceiver mPhoneAppBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -210,17 +184,4 @@
intent.getStringExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME);
}
};
-
- private final ContentObserver mSmsContentObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- if (Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING).equals(uri)) {
- mDefaultSmsApp.put(userId, Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.SMS_DEFAULT_APPLICATION, userId));
-
- }
- }
- };
}