diff --git a/api/current.txt b/api/current.txt index 49c12725f43c2..b5def49c16311 100644 --- a/api/current.txt +++ b/api/current.txt @@ -33264,11 +33264,11 @@ package android.service.notification { method public int getSuppressedVisualEffects(); method public boolean isAmbient(); method public boolean matchesInterruptionFilter(); - field public static final int IMPORTANCE_DEFAULT = 0; // 0x0 - field public static final int IMPORTANCE_HIGH = 1; // 0x1 - field public static final int IMPORTANCE_LOW = -1; // 0xffffffff - field public static final int IMPORTANCE_MAX = 2; // 0x2 - field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe + field public static final int IMPORTANCE_DEFAULT = 2; // 0x2 + field public static final int IMPORTANCE_HIGH = 3; // 0x3 + field public static final int IMPORTANCE_LOW = 1; // 0x1 + field public static final int IMPORTANCE_MAX = 4; // 0x4 + field public static final int IMPORTANCE_NONE = 0; // 0x0 field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18 } diff --git a/api/system-current.txt b/api/system-current.txt index 0fe65c33e4f73..34377fcaede7b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -35398,11 +35398,11 @@ package android.service.notification { method public int getSuppressedVisualEffects(); method public boolean isAmbient(); method public boolean matchesInterruptionFilter(); - field public static final int IMPORTANCE_DEFAULT = 0; // 0x0 - field public static final int IMPORTANCE_HIGH = 1; // 0x1 - field public static final int IMPORTANCE_LOW = -1; // 0xffffffff - field public static final int IMPORTANCE_MAX = 2; // 0x2 - field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe + field public static final int IMPORTANCE_DEFAULT = 2; // 0x2 + field public static final int IMPORTANCE_HIGH = 3; // 0x3 + field public static final int IMPORTANCE_LOW = 1; // 0x1 + field public static final int IMPORTANCE_MAX = 4; // 0x4 + field public static final int IMPORTANCE_NONE = 0; // 0x0 field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18 } diff --git a/api/test-current.txt b/api/test-current.txt index e343cfbc404e4..5c0095795c33a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -33266,11 +33266,11 @@ package android.service.notification { method public int getSuppressedVisualEffects(); method public boolean isAmbient(); method public boolean matchesInterruptionFilter(); - field public static final int IMPORTANCE_DEFAULT = 0; // 0x0 - field public static final int IMPORTANCE_HIGH = 1; // 0x1 - field public static final int IMPORTANCE_LOW = -1; // 0xffffffff - field public static final int IMPORTANCE_MAX = 2; // 0x2 - field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe + field public static final int IMPORTANCE_DEFAULT = 2; // 0x2 + field public static final int IMPORTANCE_HIGH = 3; // 0x3 + field public static final int IMPORTANCE_LOW = 1; // 0x1 + field public static final int IMPORTANCE_MAX = 4; // 0x4 + field public static final int IMPORTANCE_NONE = 0; // 0x0 field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18 } diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index a7545f21ad228..2f10cdaabfd73 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -833,29 +833,29 @@ public abstract class NotificationListenerService extends Service { /** * A notification with no importance: shows nowhere, is blocked. */ - public static final int IMPORTANCE_NONE = -2; + public static final int IMPORTANCE_NONE = 0; /** * Low notification importance: only shows in the shade, below the fold. */ - public static final int IMPORTANCE_LOW = -1; + public static final int IMPORTANCE_LOW = 1; /** * Default notification importance: shows everywhere, but is not intrusive. */ - public static final int IMPORTANCE_DEFAULT = 0; + public static final int IMPORTANCE_DEFAULT = 2; /** * Higher notification importance: shows everywhere, makes noise, * but does not visually intrude. */ - public static final int IMPORTANCE_HIGH = 1; + public static final int IMPORTANCE_HIGH = 3; /** * Highest notification importance: shows everywhere, makes noise, * and also visually intrudes. */ - public static final int IMPORTANCE_MAX = 2; + public static final int IMPORTANCE_MAX = 4; private String mKey; private int mRank = -1; diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index e5415dfb58cb5..b6a29d328cec5 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3955,6 +3955,9 @@ To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services, and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging. + + Importance + Blocked: Never show these notifications diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index dd81f89f10c53..0573ae67ee18d 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2088,6 +2088,7 @@ + diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml index d52c27465dbb9..c9dbc79f56263 100644 --- a/packages/SystemUI/res/layout/notification_guts.xml +++ b/packages/SystemUI/res/layout/notification_guts.xml @@ -16,75 +16,77 @@ --> - + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/notification_guts" + android:visibility="gone" + android:clickable="true" + android:gravity="top|start" + android:orientation="vertical" + android:paddingEnd="8dp" + android:background="@color/notification_guts_text_color" > - - + - - - - + android:paddingStart="@*android:dimen/notification_content_margin_start" + android:paddingTop="8dp" + android:paddingBottom="16dp" > - + + + + + + + + + + + + android:src="@drawable/ic_settings" /> + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 7aff02d1f9114..d703bd65c7da1 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -100,9 +100,9 @@ @color/system_accent_color - @color/system_secondary_color - #FFFFFFFF - #b2FFFFFF + @*android:color/material_deep_teal_500 + #B2DFDB + #FFFFFFFF #FFFFFFFF #ffffff diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 6207324426598..870e0af5820a7 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -246,7 +246,10 @@ public class SwipeHelper implements Gefingerpoken { mWatchLongPress = new Runnable() { @Override public void run() { - if (mCurrView != null && !mLongPressSent) { + float pos = getPos(ev); + float delta = pos - mInitialTouchPos; + if (mCurrView != null && !mLongPressSent + && Math.abs(delta) < mPagingTouchSlop) { mLongPressSent = true; mCurrView.sendAccessibilityEvent( AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index cc6a29ae0f60e..ea0a16fdde859 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.INotificationManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -35,7 +36,6 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Resources; @@ -82,6 +82,7 @@ import android.widget.DateTimeView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.RemoteViews; +import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; @@ -902,14 +903,6 @@ public abstract class BaseStatusBar extends SystemUI implements .findViewById(com.android.internal.R.id.media_actions) != null; } - // The gear button in the guts that links to the app's own notification settings - private void startAppOwnNotificationSettingsActivity(Intent intent, - final int notificationId, final String notificationTag, final int appUid) { - intent.putExtra("notification_id", notificationId); - intent.putExtra("notification_tag", notificationTag); - startNotificationGutsIntent(intent, appUid); - } - // The (i) button in the guts that links to the system notification settings for that app private void startAppNotificationSettingsActivity(String packageName, final int appUid) { final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS); @@ -968,12 +961,13 @@ public abstract class BaseStatusBar extends SystemUI implements // app is gone, just show package name and generic icon pkgicon = pmUser.getDefaultActivityIcon(); } + ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon); - ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(sbn.getPostTime()); ((TextView) row.findViewById(R.id.pkgname)).setText(appname); + + bindTopicImportance(sbn, row); + final View settingsButton = guts.findViewById(R.id.notification_inspect_item); - final View appSettingsButton - = guts.findViewById(R.id.notification_inspect_app_provided_settings); if (appUid >= 0) { final int appUidF = appUid; settingsButton.setOnClickListener(new View.OnClickListener() { @@ -982,38 +976,72 @@ public abstract class BaseStatusBar extends SystemUI implements startAppNotificationSettingsActivity(pkg, appUidF); } }); - - final Intent appSettingsQueryIntent - = new Intent(Intent.ACTION_MAIN) - .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES) - .setPackage(pkg); - List infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0); - if (infos.size() > 0) { - appSettingsButton.setVisibility(View.VISIBLE); - appSettingsButton.setContentDescription( - mContext.getResources().getString( - R.string.status_bar_notification_app_settings_title, - appname - )); - final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent) - .setClassName(pkg, infos.get(0).activityInfo.name); - appSettingsButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - MetricsLogger.action(mContext, MetricsLogger.ACTION_APP_NOTE_SETTINGS); - startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent, - sbn.getId(), - sbn.getTag(), - appUidF); - } - }); - } else { - appSettingsButton.setVisibility(View.GONE); - } } else { settingsButton.setVisibility(View.GONE); - appSettingsButton.setVisibility(View.GONE); } + } + private void bindTopicImportance(final StatusBarNotification sbn, + ExpandableNotificationRow row) { + final INotificationManager sINM = INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + final Notification.Topic topic = sbn.getNotification().getTopic() == null + ? new Notification.Topic(Notification.TOPIC_DEFAULT, mContext.getString( + com.android.internal.R.string.default_notification_topic_label)) + : sbn.getNotification().getTopic(); + + ((TextView) row.findViewById(R.id.topic_details)).setText(topic.getLabel()); + final TextView topicSummary = ((TextView) row.findViewById(R.id.summary)); + int importance = mNotificationData.getImportance(sbn.getKey()); + SeekBar seekBar = (SeekBar) row.findViewById(R.id.seekbar); + seekBar.setMax(4); + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + topicSummary.setText(getProgressSummary(progress)); + if (fromUser) { + try { + sINM.setTopicImportance(sbn.getPackageName(), sbn.getUid(), topic, + progress); + } catch (RemoteException e) { + // :( + } + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // no-op + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // no-op + } + + private String getProgressSummary(int progress) { + switch (progress) { + case NotificationListenerService.Ranking.IMPORTANCE_NONE: + return mContext.getString( + com.android.internal.R.string.notification_importance_blocked); + case NotificationListenerService.Ranking.IMPORTANCE_LOW: + return mContext.getString( + com.android.internal.R.string.notification_importance_low); + case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT: + return mContext.getString( + com.android.internal.R.string.notification_importance_default); + case NotificationListenerService.Ranking.IMPORTANCE_HIGH: + return mContext.getString( + com.android.internal.R.string.notification_importance_high); + case NotificationListenerService.Ranking.IMPORTANCE_MAX: + return mContext.getString( + com.android.internal.R.string.notification_importance_max); + default: + return ""; + } + } + }); + seekBar.setProgress(importance); } protected SwipeHelper.LongPressListener getNotificationLongClicker() { @@ -1048,6 +1076,7 @@ public abstract class BaseStatusBar extends SystemUI implements MetricsLogger.action(mContext, MetricsLogger.ACTION_NOTE_CONTROLS); guts.setVisibility(View.VISIBLE); + final double horz = Math.max(guts.getWidth() - x, x); final double vert = Math.max(guts.getActualHeight() - y, y); final float r = (float) Math.hypot(horz, vert); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 89edae316ae05..d6f2ec881adb5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -283,7 +283,7 @@ public class NotificationData { mRankingMap.getRanking(key, mTmpRanking); return mTmpRanking.getVisibilityOverride(); } - return NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE; + return Ranking.VISIBILITY_NO_OVERRIDE; } public boolean shouldSuppressPeek(String key) { @@ -295,6 +295,14 @@ public class NotificationData { return false; } + public int getImportance(String key) { + if (mRankingMap != null) { + mRankingMap.getRanking(key, mTmpRanking); + return mTmpRanking.getImportance(); + } + return Ranking.IMPORTANCE_UNSPECIFIED; + } + private void updateRankingAndSort(RankingMap ranking) { if (ranking != null) { mRankingMap = ranking; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java index 46e0bf86fd36c..0081496d23512 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java @@ -21,12 +21,14 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.FrameLayout; +import android.widget.LinearLayout; + import com.android.systemui.R; /** * The guts of a notification revealed when performing a long press. */ -public class NotificationGuts extends FrameLayout { +public class NotificationGuts extends LinearLayout { private Drawable mBackground; private int mClipTopAmount; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index c83012c0d2d6a..87108a4e42e0f 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1246,7 +1246,7 @@ public class NotificationManagerService extends SystemService { @Override public void setTopicImportance(String pkg, int uid, Notification.Topic topic, int importance) { - checkCallerIsSystem(); + enforceSystemOrSystemUI("Caller not system or systemui"); mRankingHelper.setTopicImportance(pkg, uid, topic, importance); savePolicyFile(); } diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java index 8eb30d23b206c..cf1a4aa97c6da 100644 --- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java +++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java @@ -162,8 +162,11 @@ public class NotificationTestList extends TestActivity new Test("with topic Hello") { public void run() { + Notification.BigTextStyle bigText = new Notification.BigTextStyle(); + bigText.bigText("FgBHreherhethethethe\ntwetwrterter\netetweterteryetry"); Notification n = new Notification.Builder(NotificationTestList.this) .setSmallIcon(R.drawable.icon1) + .setStyle(bigText) .setWhen(mActivityCreateTime) .setContentTitle("hihi") .setContentText("This is a notification!!!")