NotificationListenerService.java revision 3aa5f1eec08e6c3233f13935ea45c833433a2d27
108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller/* 208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * Copyright (C) 2013 The Android Open Source Project 308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * 408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * you may not use this file except in compliance with the License. 608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * You may obtain a copy of the License at 708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * 808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * http://www.apache.org/licenses/LICENSE-2.0 908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * 1008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * Unless required by applicable law or agreed to in writing, software 1108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * distributed under the License is distributed on an "AS IS" BASIS, 1208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * See the License for the specific language governing permissions and 1408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * limitations under the License. 1508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */ 1608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller 17ebbf205bc6e8292f74d8fc4652c70274a445f907Jim Millerpackage android.service.notification; 1808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller 19ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.os.Handler; 20ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.os.Looper; 21f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.os.Message; 2208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller 2308fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.annotation.IntDef; 24a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.annotation.SystemApi; 259f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport android.annotation.SdkConstant; 26ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.app.INotificationManager; 2708fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.app.Notification; 2808fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.app.Notification.Builder; 29f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.app.NotificationManager; 3008fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.app.Service; 3108fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.content.ComponentName; 32dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinimport android.content.Context; 3308fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.content.Intent; 34a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.content.pm.ParceledListSlice; 3508fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.graphics.drawable.BitmapDrawable; 369f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport android.graphics.drawable.Drawable; 37ba67aee02cf864793129976cd8a8a46e60c60577Jim Millerimport android.graphics.drawable.Icon; 38ba67aee02cf864793129976cd8a8a46e60c60577Jim Millerimport android.graphics.Bitmap; 399f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport android.os.Build; 40b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Millerimport android.os.Bundle; 419f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport android.os.IBinder; 42f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.os.Parcel; 43f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.os.Parcelable; 44f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.os.RemoteException; 4508fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.ServiceManager; 4608fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.util.ArrayMap; 47ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.util.ArraySet; 48ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.util.Log; 49ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.widget.RemoteViews; 50ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport com.android.internal.annotations.GuardedBy; 5108fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport com.android.internal.os.SomeArgs; 5208fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport java.lang.annotation.Retention; 5308fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport java.lang.annotation.RetentionPolicy; 5408fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport java.util.ArrayList; 55d08c2aceb238b02d8348518a2c87693054c6ce37Jim Millerimport java.util.Collections; 5608fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport java.util.List; 57a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 58f501b58de8f467a80fef49c704555781bc61ea6fJim Miller/** 59f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * A service that receives calls from the system when new notifications are 60f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * posted or removed, or their ranking changed. 61f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * <p>To extend this class, you must declare the service in your manifest file with 6208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * the {@link android.Manifest.permission#BIND_NOTIFICATION_LISTENER_SERVICE} permission 63ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p> 64ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <pre> 65ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <service android:name=".NotificationListener" 66ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * android:label="@string/service_name" 6708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> 68ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <intent-filter> 69ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <action android:name="android.service.notification.NotificationListenerService" /> 70ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * </intent-filter> 7108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * </service></pre> 72ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 73ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 74ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * before performing any operations. The {@link #requestRebind(ComponentName)} 75ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * method is the <i>only</i> one that is safe to call before {@link #onListenerConnected()} 76a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * or after {@link #onListenerDisconnected()}. 77ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * </p> 78ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 79ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerpublic abstract class NotificationListenerService extends Service { 80ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 81ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller // TAG = "NotificationListenerService[MySubclass]" 82ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller private final String TAG = NotificationListenerService.class.getSimpleName() 8308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller + "[" + getClass().getSimpleName() + "]"; 84ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 85ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 86ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link #getCurrentInterruptionFilter() Interruption filter} constant - 87ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Normal interruption filter. 88ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 8908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller public static final int INTERRUPTION_FILTER_ALL 90ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller = NotificationManager.INTERRUPTION_FILTER_ALL; 91ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 92ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 93ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link #getCurrentInterruptionFilter() Interruption filter} constant - 94ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Priority interruption filter. 95ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public static final int INTERRUPTION_FILTER_PRIORITY 97ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller = NotificationManager.INTERRUPTION_FILTER_PRIORITY; 98ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 99ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 100ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link #getCurrentInterruptionFilter() Interruption filter} constant - 101ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * No interruptions filter. 102ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 103ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int INTERRUPTION_FILTER_NONE 104ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller = NotificationManager.INTERRUPTION_FILTER_NONE; 105ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 106fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller /** 107fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller * {@link #getCurrentInterruptionFilter() Interruption filter} constant - 108fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller * Alarms only interruption filter. 109fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller */ 110fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller public static final int INTERRUPTION_FILTER_ALARMS 111ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller = NotificationManager.INTERRUPTION_FILTER_ALARMS; 112ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 113ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** {@link #getCurrentInterruptionFilter() Interruption filter} constant - returned when 114f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * the value is unavailable for any reason. For example, before the notification listener 115ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * is connected. 1169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 11708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * {@see #onListenerConnected()} 118ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 119ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int INTERRUPTION_FILTER_UNKNOWN 120ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller = NotificationManager.INTERRUPTION_FILTER_UNKNOWN; 121ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 122ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI 123ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * should disable notification sound, vibrating and other visual or aural effects. 124ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * This does not change the interruption filter, only the effects. **/ 125a7596147b43940cad3f76c53ed154ef088b9269bJim Miller public static final int HINT_HOST_DISABLE_EFFECTS = 1; 126ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 127ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI 128ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * should disable notification sound, but not phone calls. 129ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * This does not change the interruption filter, only the effects. **/ 130ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 1 << 1; 131a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 132ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI 133ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * should disable phone call sounds, buyt not notification sound. 134ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * This does not change the interruption filter, only the effects. **/ 135ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 1 << 2; 136ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 137a7596147b43940cad3f76c53ed154ef088b9269bJim Miller /** 138ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Whether notification suppressed by DND should not interruption visually when the screen is 139ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * off. 140ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 141ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 142ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; 143ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 144ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Whether notification suppressed by DND should not interruption visually when the screen is 145ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * on. 1469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller */ 147ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int SUPPRESSED_EFFECT_SCREEN_ON = 148ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; 149ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 150ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 151ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller // Notification cancellation reasons 1529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 153ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the status bar reporting a click. */ 154ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_DELEGATE_CLICK = 1; 155ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the status bar reporting a user dismissal. */ 156ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_DELEGATE_CANCEL = 2; 157ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the status bar reporting a user dismiss all. */ 158ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_DELEGATE_CANCEL_ALL = 3; 159ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the status bar reporting an inflation error. */ 1609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public static final int REASON_DELEGATE_ERROR = 4; 161ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the package manager modifying the package. */ 162ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_PACKAGE_CHANGED = 5; 163ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the owning user context being stopped. */ 164ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_USER_STOPPED = 6; 165f501b58de8f467a80fef49c704555781bc61ea6fJim Miller /** Notification was canceled by the user banning the package. */ 166ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_PACKAGE_BANNED = 7; 1679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** Notification was canceled by the app canceling this specific notification. */ 168a7596147b43940cad3f76c53ed154ef088b9269bJim Miller public static final int REASON_APP_CANCEL = 8; 16908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller /** Notification was canceled by the app cancelling all its notifications. */ 170d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller public static final int REASON_APP_CANCEL_ALL = 9; 171a7596147b43940cad3f76c53ed154ef088b9269bJim Miller /** Notification was canceled by a listener reporting a user dismissal. */ 1729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public static final int REASON_LISTENER_CANCEL = 10; 1739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** Notification was canceled by a listener reporting a user dismiss all. */ 1749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public static final int REASON_LISTENER_CANCEL_ALL = 11; 1759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** Notification was canceled because it was a member of a canceled group. */ 1769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public static final int REASON_GROUP_SUMMARY_CANCELED = 12; 177f501b58de8f467a80fef49c704555781bc61ea6fJim Miller /** Notification was canceled because it was an invisible member of a group. */ 178ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_GROUP_OPTIMIZATION = 13; 179ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the device administrator suspending the package. */ 180ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_PACKAGE_SUSPENDED = 14; 181ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the owning managed profile being turned off. */ 182fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller public static final int REASON_PROFILE_TURNED_OFF = 15; 183ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Autobundled summary notification was canceled because its group was unbundled */ 184ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_UNAUTOBUNDLED = 16; 185ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was canceled by the user banning the channel. */ 186ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_CHANNEL_BANNED = 17; 187ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification was snoozed. */ 188ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_SNOOZED = 18; 189ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** Notification no longer visible because of user switch */ 190ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int REASON_USER_SWITCH = 19; 191ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 192ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 193ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * The full trim of the StatusBarNotification including all its features. 194ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 195ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @hide 196ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 197ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @SystemApi 19808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller public static final int TRIM_FULL = 0; 1999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 200ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 201b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * A light trim of the StatusBarNotification excluding the following features: 2029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 203f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * <ol> 204ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <li>{@link Notification#tickerView tickerView}</li> 205b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * <li>{@link Notification#contentView contentView}</li> 206f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * <li>{@link Notification#largeIcon largeIcon}</li> 207ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <li>{@link Notification#bigContentView bigContentView}</li> 208ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <li>{@link Notification#headsUpContentView headsUpContentView}</li> 209b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * <li>{@link Notification#EXTRA_LARGE_ICON extras[EXTRA_LARGE_ICON]}</li> 210f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * <li>{@link Notification#EXTRA_LARGE_ICON_BIG extras[EXTRA_LARGE_ICON_BIG]}</li> 211b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * <li>{@link Notification#EXTRA_PICTURE extras[EXTRA_PICTURE]}</li> 212b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * <li>{@link Notification#EXTRA_BIG_TEXT extras[EXTRA_BIG_TEXT]}</li> 213b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * </ol> 214f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * 215ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @hide 216ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 217ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @SystemApi 218ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public static final int TRIM_LIGHT = 1; 219ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 220ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller private final Object mLock = new Object(); 221f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 222f501b58de8f467a80fef49c704555781bc61ea6fJim Miller private Handler mHandler; 223f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 224ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** @hide */ 225ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller protected NotificationListenerWrapper mWrapper = null; 226ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller private boolean isConnected = false; 227ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 228ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @GuardedBy("mLock") 229f501b58de8f467a80fef49c704555781bc61ea6fJim Miller private RankingMap mRankingMap; 230f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 231f501b58de8f467a80fef49c704555781bc61ea6fJim Miller private INotificationManager mNoMan; 232ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 233ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 234b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * Only valid after a successful call to (@link registerAsService}. 235b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * @hide 236b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller */ 237f501b58de8f467a80fef49c704555781bc61ea6fJim Miller protected int mCurrentUser; 238f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 239f501b58de8f467a80fef49c704555781bc61ea6fJim Miller /** 240b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * This context is required for system services since NotificationListenerService isn't 241b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller * started as a real Service and hence no context is available.. 242ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @hide 243ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 244ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller protected Context mSystemContext; 245ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 246f501b58de8f467a80fef49c704555781bc61ea6fJim Miller /** 247f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * The {@link Intent} that must be declared as handled by the service. 248ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 249ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 250f501b58de8f467a80fef49c704555781bc61ea6fJim Miller public static final String SERVICE_INTERFACE 25108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller = "android.service.notification.NotificationListenerService"; 25208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller 2539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller @Override 2549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller protected void attachBaseContext(Context base) { 255f501b58de8f467a80fef49c704555781bc61ea6fJim Miller super.attachBaseContext(base); 2569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller mHandler = new MyHandler(getMainLooper()); 2579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 2589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 2599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 2609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Implement this method to learn about new notifications as they are posted by apps. 261f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * 262f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * @param sbn A data structure encapsulating the original {@link android.app.Notification} 263f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * object as well as its identifying information (tag and id) and source 264f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * (package name). 265f501b58de8f467a80fef49c704555781bc61ea6fJim Miller */ 266f501b58de8f467a80fef49c704555781bc61ea6fJim Miller public void onNotificationPosted(StatusBarNotification sbn) { 267f501b58de8f467a80fef49c704555781bc61ea6fJim Miller // optional 2689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 2699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 2709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 271ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller * Implement this method to learn about new notifications as they are posted by apps. 2729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 2739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @param sbn A data structure encapsulating the original {@link android.app.Notification} 2749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * object as well as its identifying information (tag and id) and source 2759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * (package name). 276f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * @param rankingMap The current ranking map that can be used to retrieve ranking information 2779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * for active notifications, including the newly posted one. 2789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller */ 2799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) { 2809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller onNotificationPosted(sbn); 281ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 282ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 283ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 2849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Implement this method to learn when notifications are removed. 2859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 2869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * This might occur because the user has dismissed the notification using system UI (or another 2879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * notification listener) or because the app has withdrawn the notification. 288ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller * <p> 28906e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the 2909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight 291f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * fields such as {@link android.app.Notification#contentView} and 292ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link android.app.Notification#largeIcon}. However, all other fields on 293f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * {@link StatusBarNotification}, sufficient to match this call with a prior call to 294ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link #onNotificationPosted(StatusBarNotification)}, will be intact. 29506e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller * 2969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @param sbn A data structure encapsulating at least the original information (tag and id) 2979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * and source (package name) used to post the {@link android.app.Notification} that 2989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * was just removed. 2999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller */ 300f501b58de8f467a80fef49c704555781bc61ea6fJim Miller public void onNotificationRemoved(StatusBarNotification sbn) { 301ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller // optional 3029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 303f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 30408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller /** 3059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Implement this method to learn when notifications are removed. 306ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p> 3079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * This might occur because the user has dismissed the notification using system UI (or another 3089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * notification listener) or because the app has withdrawn the notification. 309f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * <p> 310ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the 3119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight 312f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * fields such as {@link android.app.Notification#contentView} and 31308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * {@link android.app.Notification#largeIcon}. However, all other fields on 3149f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * {@link StatusBarNotification}, sufficient to match this call with a prior call to 3159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * {@link #onNotificationPosted(StatusBarNotification)}, will be intact. 316ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 3179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @param sbn A data structure encapsulating at least the original information (tag and id) 318ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * and source (package name) used to post the {@link android.app.Notification} that 319ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * was just removed. 320ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param rankingMap The current ranking map that can be used to retrieve ranking information 321ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * for active notifications. 322ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 323ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 3249f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) { 32508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller onNotificationRemoved(sbn); 3269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 3279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 3289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 3299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 330f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * Implement this method to learn when notifications are removed and why. 331ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p> 332ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * This might occur because the user has dismissed the notification using system UI (or another 3339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * notification listener) or because the app has withdrawn the notification. 3349f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 3359f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the 3369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight 3379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * fields such as {@link android.app.Notification#contentView} and 338ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link android.app.Notification#largeIcon}. However, all other fields on 339ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link StatusBarNotification}, sufficient to match this call with a prior call to 3409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * {@link #onNotificationPosted(StatusBarNotification)}, will be intact. 341ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 342a7596147b43940cad3f76c53ed154ef088b9269bJim Miller ** @param sbn A data structure encapsulating at least the original information (tag and id) 3439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * and source (package name) used to post the {@link android.app.Notification} that 344ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * was just removed. 3459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @param rankingMap The current ranking map that can be used to retrieve ranking information 3469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * for active notifications. 3479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @param reason see {@link #REASON_LISTENER_CANCEL}, etc. 348ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 349ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap, 3509f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller int reason) { 351ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller onNotificationRemoved(sbn, rankingMap); 35208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } 3539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 3549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 355ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Implement this method to learn about when the listener is enabled and connected to 3569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * the notification manager. You are safe to call {@link #getActiveNotifications()} 357ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * at this time. 3589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller */ 359ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void onListenerConnected() { 3609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller // optional 36108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } 3629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 3639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 3649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Implement this method to learn about when the listener is disconnected from the 3659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * notification manager.You will not receive any events after this call, and may only 3669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * call {@link #requestRebind(ComponentName)} at this time. 367ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 368ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void onListenerDisconnected() { 3699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller // optional 3709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 3719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 3729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 373ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Implement this method to be notified when the notification ranking changes. 374ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 375ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param rankingMap The current ranking map that can be used to retrieve ranking information 3769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * for active notifications. 377ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 3789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public void onNotificationRankingUpdate(RankingMap rankingMap) { 3799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller // optional 3809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 3819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 3829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 383ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Implement this method to be notified when the 38408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * {@link #getCurrentListenerHints() Listener hints} change. 38508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * 38608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * @param hints The current {@link #getCurrentListenerHints() listener hints}. 387ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 388ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void onListenerHintsChanged(int hints) { 3899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller // optional 3909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 3919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 3929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 393d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller * Implement this method to be notified when the 3949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * {@link #getCurrentInterruptionFilter() interruption filter} changed. 3959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 396ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param interruptionFilter The current 397f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * {@link #getCurrentInterruptionFilter() interruption filter}. 398f501b58de8f467a80fef49c704555781bc61ea6fJim Miller */ 399d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller public void onInterruptionFilterChanged(int interruptionFilter) { 400f501b58de8f467a80fef49c704555781bc61ea6fJim Miller // optional 401ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 402f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 403f501b58de8f467a80fef49c704555781bc61ea6fJim Miller /** @hide */ 404ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi protected final INotificationManager getNotificationInterface() { 405ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi if (mNoMan == null) { 406ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi mNoMan = INotificationManager.Stub.asInterface( 407f501b58de8f467a80fef49c704555781bc61ea6fJim Miller ServiceManager.getService(Context.NOTIFICATION_SERVICE)); 408f501b58de8f467a80fef49c704555781bc61ea6fJim Miller } 409f501b58de8f467a80fef49c704555781bc61ea6fJim Miller return mNoMan; 410f501b58de8f467a80fef49c704555781bc61ea6fJim Miller } 411f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 412f501b58de8f467a80fef49c704555781bc61ea6fJim Miller /** 413f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * Inform the notification manager about dismissal of a single notification. 414f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * <p> 415f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * Use this if your listener has a user interface that allows the user to dismiss individual 416f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * notifications, similar to the behavior of Android's status bar and notification panel. 417f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * It should be called after the user dismisses a single notification using your UI; 418f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * upon being informed, the notification manager will actually remove the notification 419f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback. 420ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi * <p> 421ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi * <b>Note:</b> If your listener allows the user to fire a notification's 422f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call 423ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi * this method at that time <i>if</i> the Notification in question has the 424f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set. 4259f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 4269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 4279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * before performing this operation. 4289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 429ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param pkg Package of the notifying app. 430ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param tag Tag of the notification as specified by the notifying app in 431ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}. 432ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param id ID of the notification as specified by the notifying app in 433ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}. 434ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p> 435ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @deprecated Use {@link #cancelNotification(String key)} 436ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * instead. Beginning with {@link android.os.Build.VERSION_CODES#LOLLIPOP} this method will no longer 4379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * cancel the notification. It will continue to cancel the notification for applications 4389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * whose {@code targetSdkVersion} is earlier than {@link android.os.Build.VERSION_CODES#LOLLIPOP}. 439f501b58de8f467a80fef49c704555781bc61ea6fJim Miller */ 4409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller @Deprecated 4419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public final void cancelNotification(String pkg, String tag, int id) { 442ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller if (!isBound()) return; 4434af76a51d5082c740609563e07cf35f30bc2224eSvetoslav try { 4444af76a51d5082c740609563e07cf35f30bc2224eSvetoslav getNotificationInterface().cancelNotificationFromListener( 4459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller mWrapper, pkg, tag, id); 446ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } catch (android.os.RemoteException ex) { 447ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller Log.v(TAG, "Unable to contact notification manager", ex); 448ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 449ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 450ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 451ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 452ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Inform the notification manager about dismissal of a single notification. 4539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 454d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller * Use this if your listener has a user interface that allows the user to dismiss individual 455d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller * notifications, similar to the behavior of Android's status bar and notification panel. 456d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller * It should be called after the user dismisses a single notification using your UI; 4579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * upon being informed, the notification manager will actually remove the notification 4589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback. 4599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 4609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <b>Note:</b> If your listener allows the user to fire a notification's 4619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call 4629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * this method at that time <i>if</i> the Notification in question has the 4639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set. 464fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller * <p> 465fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller * 4669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 4679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * before performing this operation. 468f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * 469ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param key Notification to dismiss from {@link StatusBarNotification#getKey()}. 47008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */ 471f501b58de8f467a80fef49c704555781bc61ea6fJim Miller public final void cancelNotification(String key) { 472f501b58de8f467a80fef49c704555781bc61ea6fJim Miller if (!isBound()) return; 473f501b58de8f467a80fef49c704555781bc61ea6fJim Miller try { 4749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller getNotificationInterface().cancelNotificationsFromListener(mWrapper, 4759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller new String[] { key }); 47608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } catch (android.os.RemoteException ex) { 4779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller Log.v(TAG, "Unable to contact notification manager", ex); 478ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 479ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 480ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 481ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 482ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Inform the notification manager about dismissal of all notifications. 483fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller * <p> 484ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Use this if your listener has a user interface that allows the user to dismiss all 485ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * notifications, similar to the behavior of Android's status bar and notification panel. 4869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * It should be called after the user invokes the "dismiss all" function of your UI; 48708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * upon being informed, the notification manager will actually remove all active notifications 4889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * and you will get multiple {@link #onNotificationRemoved(StatusBarNotification)} callbacks. 489fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller * 490ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 491ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * before performing this operation. 492ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 493ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@see #cancelNotification(String, String, int)} 494ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 495ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public final void cancelAllNotifications() { 496ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller cancelNotifications(null /*all*/); 497ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 498ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 499ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 500ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Inform the notification manager about dismissal of specific notifications. 501ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p> 502ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Use this if your listener has a user interface that allows the user to dismiss 503ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * multiple notifications at once. 504ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 505ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 506f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * before performing this operation. 507ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 508ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param keys Notifications to dismiss, or {@code null} to dismiss all. 509ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 510ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@see #cancelNotification(String, String, int)} 51108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */ 512ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public final void cancelNotifications(String[] keys) { 51308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller if (!isBound()) return; 514ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller try { 51508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller getNotificationInterface().cancelNotificationsFromListener(mWrapper, keys); 51608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } catch (android.os.RemoteException ex) { 51708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller Log.v(TAG, "Unable to contact notification manager", ex); 5189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 5199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 5209f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 521ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 522ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Inform the notification manager about snoozing a specific notification. 5239f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 52408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * Use this if your listener has a user interface that allows the user to snooze a notification 525f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * until a given time. It should be called after the user snoozes a single notification using 5269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * your UI; upon being informed, the notification manager will actually remove the notification 5279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback. When the 5289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * snoozing period expires, you will get a 5299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * {@link #onNotificationPosted(StatusBarNotification, RankingMap)} callback for the 530ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * notification. 5319f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @param key The key of the notification to snooze 532ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param snoozeUntil A time in the future, in milliseconds. 533ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 534ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public final void snoozeNotification(String key, long snoozeUntil) { 535ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller if (!isBound()) return; 536ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller try { 53708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller getNotificationInterface().snoozeNotificationFromListener(mWrapper, key, snoozeUntil); 53808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } catch (android.os.RemoteException ex) { 53908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller Log.v(TAG, "Unable to contact notification manager", ex); 54008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } 5419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 5429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 5439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 544ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Inform the notification manager that these notifications have been viewed by the 5459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * user. This should only be called when there is sufficient confidence that the user is 54608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * looking at the notifications, such as when the notifications appear on the screen due to 547f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * an explicit user interaction. 5489f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 5499f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 55008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * before performing this operation. 55108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * 5529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @param keys Notifications to mark as seen. 55308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */ 5549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public final void setNotificationsShown(String[] keys) { 55508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller if (!isBound()) return; 556a7596147b43940cad3f76c53ed154ef088b9269bJim Miller try { 5579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller getNotificationInterface().setNotificationsShownFromListener(mWrapper, keys); 55808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } catch (android.os.RemoteException ex) { 55908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller Log.v(TAG, "Unable to contact notification manager", ex); 56008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } 5619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 5629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 5639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 564ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Sets the notification trim that will be received via {@link #onNotificationPosted}. 565ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 5669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 567f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * Setting a trim other than {@link #TRIM_FULL} enables listeners that don't need access to the 5682aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * full notification features right away to reduce their memory footprint. Full notifications 5699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * can be requested on-demand via {@link #getActiveNotifications(int)}. 5704af76a51d5082c740609563e07cf35f30bc2224eSvetoslav * 57108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * <p> 5729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Set to {@link #TRIM_FULL} initially. 57308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * 5749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 57508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * before performing this operation. 57608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * 57708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * @hide 5782aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * 5792aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * @param trim trim of the notifications to be passed via {@link #onNotificationPosted}. 580ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * See <code>TRIM_*</code> constants. 5819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller */ 58208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller @SystemApi 583f501b58de8f467a80fef49c704555781bc61ea6fJim Miller public final void setOnNotificationPostedTrim(int trim) { 5842aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi if (!isBound()) return; 5852aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi try { 5862aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi getNotificationInterface().setOnNotificationPostedTrimFromListener(mWrapper, trim); 5872aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi } catch (RemoteException ex) { 5882aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi Log.v(TAG, "Unable to contact notification manager", ex); 5892aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi } 5902aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi } 5912aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi 5922aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi /** 593f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * Request the list of outstanding notifications (that is, those that are visible to the 5942aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * current user). Useful when you don't know what's already been posted. 5952aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * 5964af76a51d5082c740609563e07cf35f30bc2224eSvetoslav * <p>The service should wait for the {@link #onListenerConnected()} event 5974af76a51d5082c740609563e07cf35f30bc2224eSvetoslav * before performing this operation. 5982aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * 5992aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * @return An array of active notifications, sorted in natural order. 6002aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi */ 6012aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi public StatusBarNotification[] getActiveNotifications() { 6022aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi return getActiveNotifications(null, TRIM_FULL); 6032aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi } 6042aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi 6052aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi /** 6062aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * Request the list of outstanding notifications (that is, those that are visible to the 6072aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * current user). Useful when you don't know what's already been posted. 6082aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi * 609f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * @hide 6109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 61108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * @param trim trim of the notifications to be returned. See <code>TRIM_*</code> constants. 61208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * @return An array of active notifications, sorted in natural order. 6139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller */ 6144af76a51d5082c740609563e07cf35f30bc2224eSvetoslav @SystemApi 61508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller public StatusBarNotification[] getActiveNotifications(int trim) { 6169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller return getActiveNotifications(null, trim); 61708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } 61808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller 6199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 620a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * Request one or more notifications by key. Useful if you have been keeping track of 6219f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * notifications but didn't want to retain the bits, and now need to go back and extract 622a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * more data out of those notifications. 623a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * 6244d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * <p>The service should wait for the {@link #onListenerConnected()} event 6254d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * before performing this operation. 6264d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * 6274d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * @param keys the keys of the notifications to request 6284d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * @return An array of notifications corresponding to the requested keys, in the 6294d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * same order as the key list. 6304d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales */ 6314d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales public StatusBarNotification[] getActiveNotifications(String[] keys) { 6324d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales return getActiveNotifications(keys, TRIM_FULL); 6334af76a51d5082c740609563e07cf35f30bc2224eSvetoslav } 6344d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales 6354d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales /** 6364d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * Request one or more notifications by key. Useful if you have been keeping track of 6374d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * notifications but didn't want to retain the bits, and now need to go back and extract 6384d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * more data out of those notifications. 6394d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * 6404d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * @hide 6414d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * 6424d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * @param keys the keys of the notifications to request 64324e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin * @param trim trim of the notifications to be returned. See <code>TRIM_*</code> constants. 64424e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin * @return An array of notifications corresponding to the requested keys, in the 64524e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin * same order as the key list. 64624e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin */ 64724e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin @SystemApi 648f501b58de8f467a80fef49c704555781bc61ea6fJim Miller public StatusBarNotification[] getActiveNotifications(String[] keys, int trim) { 649f501b58de8f467a80fef49c704555781bc61ea6fJim Miller if (!isBound()) 650f501b58de8f467a80fef49c704555781bc61ea6fJim Miller return null; 651f501b58de8f467a80fef49c704555781bc61ea6fJim Miller try { 6529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller ParceledListSlice<StatusBarNotification> parceledList = getNotificationInterface() 6539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller .getActiveNotificationsFromListener(mWrapper, keys, trim); 6549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller List<StatusBarNotification> list = parceledList.getList(); 6559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller ArrayList<StatusBarNotification> corruptNotifications = null; 6569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller int N = list.size(); 6579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller for (int i = 0; i < N; i++) { 6589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller StatusBarNotification sbn = list.get(i); 6599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller Notification notification = sbn.getNotification(); 660f501b58de8f467a80fef49c704555781bc61ea6fJim Miller try { 661f501b58de8f467a80fef49c704555781bc61ea6fJim Miller // convert icon metadata to legacy format for older clients 662f501b58de8f467a80fef49c704555781bc61ea6fJim Miller createLegacyIconExtras(notification); 663f501b58de8f467a80fef49c704555781bc61ea6fJim Miller // populate remote views for older clients. 664f501b58de8f467a80fef49c704555781bc61ea6fJim Miller maybePopulateRemoteViews(notification); 6659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } catch (IllegalArgumentException e) { 6669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller if (corruptNotifications == null) { 6679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller corruptNotifications = new ArrayList<>(N); 6689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 6699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller corruptNotifications.add(sbn); 6709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller Log.w(TAG, "onNotificationPosted: can't rebuild notification from " + 6719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller sbn.getPackageName()); 6729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 67308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller } 6749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller if (corruptNotifications != null) { 6759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller list.removeAll(corruptNotifications); 6769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 6779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller return list.toArray(new StatusBarNotification[list.size()]); 6789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } catch (android.os.RemoteException ex) { 6799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller Log.v(TAG, "Unable to contact notification manager", ex); 6809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 6819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller return null; 6829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 6839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 6849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 6859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Gets the set of hints representing current state. 686a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * 687a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * <p> 688a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * The current state may differ from the requested state if the hint represents state 6899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * shared across all listeners or a feature the notification host does not support or refuses 6909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * to grant. 6919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 6929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 6939f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * before performing this operation. 6949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 6959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @return Zero or more of the HINT_ constants. 6969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller */ 6979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public final int getCurrentListenerHints() { 6989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller if (!isBound()) return 0; 6999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller try { 7009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller return getNotificationInterface().getHintsFromListener(mWrapper); 7019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } catch (android.os.RemoteException ex) { 7029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller Log.v(TAG, "Unable to contact notification manager", ex); 7039f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller return 0; 7049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 7059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 706f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 7079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 708f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * Gets the current notification interruption filter active on the host. 709f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * 710f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * <p> 711f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * The interruption filter defines which notifications are allowed to interrupt the user 712f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * (e.g. via sound & vibration) and is applied globally. Listeners can find out whether 713f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * a specific notification matched the interruption filter via 714f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * {@link Ranking#matchesInterruptionFilter()}. 715f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * <p> 7169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * The current filter may differ from the previously requested filter if the notification host 7179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * does not support or refuses to apply the requested filter, or if another component changed 7189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * the filter in the meantime. 7199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 7209f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Listen for updates using {@link #onInterruptionFilterChanged(int)}. 7219f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 7229f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 7239f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * before performing this operation. 7249f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 7259f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when 7269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * unavailable. 7279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller */ 7289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public final int getCurrentInterruptionFilter() { 7299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller if (!isBound()) return INTERRUPTION_FILTER_UNKNOWN; 730ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller try { 731ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller return getNotificationInterface().getInterruptionFilterFromListener(mWrapper); 732ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller } catch (android.os.RemoteException ex) { 733ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller Log.v(TAG, "Unable to contact notification manager", ex); 7349f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller return INTERRUPTION_FILTER_UNKNOWN; 7359f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 7369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 7379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 7389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 7399f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Sets the desired {@link #getCurrentListenerHints() listener hints}. 74024e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin * 7419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 7429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * This is merely a request, the host may or may not choose to take action depending 7439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * on other listener requests or other global state. 7449f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p> 7459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Listen for updates using {@link #onListenerHintsChanged(int)}. 7469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 7479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 7489f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * before performing this operation. 749ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller * 750ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller * @param hints One or more of the HINT_ constants. 751ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller */ 752fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller public final void requestListenerHints(int hints) { 753ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller if (!isBound()) return; 754ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller try { 755ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller getNotificationInterface().requestHintsFromListener(mWrapper, hints); 756ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } catch (android.os.RemoteException ex) { 757ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller Log.v(TAG, "Unable to contact notification manager", ex); 758ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 759ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 760ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 761ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 7624af76a51d5082c740609563e07cf35f30bc2224eSvetoslav * Sets the desired {@link #getCurrentInterruptionFilter() interruption filter}. 763ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 764ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p> 765ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * This is merely a request, the host may or may not choose to apply the requested 766ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * interruption filter depending on other listener requests or other global state. 767ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p> 768ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Listen for updates using {@link #onInterruptionFilterChanged(int)}. 769ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 770ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 771ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * before performing this operation. 772ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 773ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @param interruptionFilter One of the INTERRUPTION_FILTER_ constants. 774ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 775ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public final void requestInterruptionFilter(int interruptionFilter) { 776ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller if (!isBound()) return; 777ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller try { 778ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller getNotificationInterface() 779ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller .requestInterruptionFilterFromListener(mWrapper, interruptionFilter); 780fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } catch (android.os.RemoteException ex) { 781fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller Log.v(TAG, "Unable to contact notification manager", ex); 782fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 783fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 784fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 785ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 786ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Returns current ranking information. 787ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 788ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p> 789ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * The returned object represents the current ranking snapshot and only 790ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * applies for currently active notifications. 791ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p> 792ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Generally you should use the RankingMap that is passed with events such 7939f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * as {@link #onNotificationPosted(StatusBarNotification, RankingMap)}, 794ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * {@link #onNotificationRemoved(StatusBarNotification, RankingMap)}, and 795ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller * so on. This method should only be used when needing access outside of 796ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller * such events, for example to retrieve the RankingMap right after 79799d6019bead4705b7e126e65b856d538417d4934Jim Miller * initialization. 798ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 799ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 800ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * before performing this operation. 801ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 802ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * @return A {@link RankingMap} object providing access to ranking information 803ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 804ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public RankingMap getCurrentRanking() { 805ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller synchronized (mLock) { 806ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller return mRankingMap; 807ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 808ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 809ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 810ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** 811ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * This is not the lifecycle event you are looking for. 812ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * 813ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>The service should wait for the {@link #onListenerConnected()} event 814ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * before performing any operations. 815ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller */ 816ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @Override 817ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public IBinder onBind(Intent intent) { 818ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller if (mWrapper == null) { 819ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller mWrapper = new NotificationListenerWrapper(); 820ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 821ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller return mWrapper; 822ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 823ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 824ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller /** @hide */ 8259f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller protected boolean isBound() { 826ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller if (mWrapper == null) { 82799d6019bead4705b7e126e65b856d538417d4934Jim Miller Log.w(TAG, "Notification listener service not yet bound."); 82899d6019bead4705b7e126e65b856d538417d4934Jim Miller return false; 8299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 8309f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller return true; 8319f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 832f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 8339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller @Override 8349f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public void onDestroy() { 8359f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller onListenerDisconnected(); 8369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller super.onDestroy(); 8379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 838f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 8399f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller /** 8409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * Directly register this service with the Notification Manager. 8419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * 8429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller * <p>Only system services may use this call. It will fail for non-system callers. 843f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * Apps should ask the user to add their listener in Settings. 844f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * 845f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * @param context Context required for accessing resources. Since this service isn't 846f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * launched as a real Service when using this method, a context has to be passed in. 847f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * @param componentName the component that will consume the notification information 848f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * @param currentUser the user to use as the stream filter 849f501b58de8f467a80fef49c704555781bc61ea6fJim Miller * @hide 850f501b58de8f467a80fef49c704555781bc61ea6fJim Miller */ 8519f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller @SystemApi 8529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller public void registerAsSystemService(Context context, ComponentName componentName, 853f501b58de8f467a80fef49c704555781bc61ea6fJim Miller int currentUser) throws RemoteException { 8549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller if (mWrapper == null) { 8559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller mWrapper = new NotificationListenerWrapper(); 8569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 8579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller mSystemContext = context; 858f501b58de8f467a80fef49c704555781bc61ea6fJim Miller INotificationManager noMan = getNotificationInterface(); 8599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller mHandler = new MyHandler(context.getMainLooper()); 8609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller mCurrentUser = currentUser; 8619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller noMan.registerListener(mWrapper, componentName, currentUser); 8629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 8639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 8644d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales /** 8654d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales * Directly unregister this service from the Notification Manager. 866 * 867 * <p>This method will fail for listeners that were not registered 868 * with (@link registerAsService). 869 * @hide 870 */ 871 @SystemApi 872 public void unregisterAsSystemService() throws RemoteException { 873 if (mWrapper != null) { 874 INotificationManager noMan = getNotificationInterface(); 875 noMan.unregisterListener(mWrapper, mCurrentUser); 876 } 877 } 878 879 /** 880 * Request that the listener be rebound, after a previous call to (@link requestUnbind). 881 * 882 * <p>This method will fail for listeners that have 883 * not been granted the permission by the user. 884 */ 885 public static void requestRebind(ComponentName componentName) { 886 INotificationManager noMan = INotificationManager.Stub.asInterface( 887 ServiceManager.getService(Context.NOTIFICATION_SERVICE)); 888 try { 889 noMan.requestBindListener(componentName); 890 } catch (RemoteException ex) { 891 throw ex.rethrowFromSystemServer(); 892 } 893 } 894 895 /** 896 * Request that the service be unbound. 897 * 898 * <p>This will no longer receive updates until 899 * {@link #requestRebind(ComponentName)} is called. 900 * The service will likely be kiled by the system after this call. 901 * 902 * <p>The service should wait for the {@link #onListenerConnected()} event 903 * before performing this operation. I know it's tempting, but you must wait. 904 */ 905 public final void requestUnbind() { 906 if (mWrapper != null) { 907 INotificationManager noMan = getNotificationInterface(); 908 try { 909 noMan.requestUnbindListener(mWrapper); 910 // Disable future messages. 911 isConnected = false; 912 } catch (RemoteException ex) { 913 throw ex.rethrowFromSystemServer(); 914 } 915 } 916 } 917 918 /** Convert new-style Icons to legacy representations for pre-M clients. */ 919 private void createLegacyIconExtras(Notification n) { 920 Icon smallIcon = n.getSmallIcon(); 921 Icon largeIcon = n.getLargeIcon(); 922 if (smallIcon != null && smallIcon.getType() == Icon.TYPE_RESOURCE) { 923 n.extras.putInt(Notification.EXTRA_SMALL_ICON, smallIcon.getResId()); 924 n.icon = smallIcon.getResId(); 925 } 926 if (largeIcon != null) { 927 Drawable d = largeIcon.loadDrawable(getContext()); 928 if (d != null && d instanceof BitmapDrawable) { 929 final Bitmap largeIconBits = ((BitmapDrawable) d).getBitmap(); 930 n.extras.putParcelable(Notification.EXTRA_LARGE_ICON, largeIconBits); 931 n.largeIcon = largeIconBits; 932 } 933 } 934 } 935 936 /** 937 * Populates remote views for pre-N targeting apps. 938 */ 939 private void maybePopulateRemoteViews(Notification notification) { 940 if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) { 941 Builder builder = Builder.recoverBuilder(getContext(), notification); 942 943 // Some styles wrap Notification's contentView, bigContentView and headsUpContentView. 944 // First inflate them all, only then set them to avoid recursive wrapping. 945 RemoteViews content = builder.createContentView(); 946 RemoteViews big = builder.createBigContentView(); 947 RemoteViews headsUp = builder.createHeadsUpContentView(); 948 949 notification.contentView = content; 950 notification.bigContentView = big; 951 notification.headsUpContentView = headsUp; 952 } 953 } 954 955 /** @hide */ 956 protected class NotificationListenerWrapper extends INotificationListener.Stub { 957 @Override 958 public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder, 959 NotificationRankingUpdate update) { 960 StatusBarNotification sbn; 961 try { 962 sbn = sbnHolder.get(); 963 } catch (RemoteException e) { 964 Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e); 965 return; 966 } 967 968 try { 969 // convert icon metadata to legacy format for older clients 970 createLegacyIconExtras(sbn.getNotification()); 971 maybePopulateRemoteViews(sbn.getNotification()); 972 } catch (IllegalArgumentException e) { 973 // warn and drop corrupt notification 974 Log.w(TAG, "onNotificationPosted: can't rebuild notification from " + 975 sbn.getPackageName()); 976 sbn = null; 977 } 978 979 // protect subclass from concurrent modifications of (@link mNotificationKeys}. 980 synchronized (mLock) { 981 applyUpdateLocked(update); 982 if (sbn != null) { 983 SomeArgs args = SomeArgs.obtain(); 984 args.arg1 = sbn; 985 args.arg2 = mRankingMap; 986 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_POSTED, 987 args).sendToTarget(); 988 } else { 989 // still pass along the ranking map, it may contain other information 990 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE, 991 mRankingMap).sendToTarget(); 992 } 993 } 994 995 } 996 997 @Override 998 public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder, 999 NotificationRankingUpdate update, int reason) { 1000 StatusBarNotification sbn; 1001 try { 1002 sbn = sbnHolder.get(); 1003 } catch (RemoteException e) { 1004 Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification", e); 1005 return; 1006 } 1007 // protect subclass from concurrent modifications of (@link mNotificationKeys}. 1008 synchronized (mLock) { 1009 applyUpdateLocked(update); 1010 SomeArgs args = SomeArgs.obtain(); 1011 args.arg1 = sbn; 1012 args.arg2 = mRankingMap; 1013 args.arg3 = reason; 1014 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED, 1015 args).sendToTarget(); 1016 } 1017 1018 } 1019 1020 @Override 1021 public void onListenerConnected(NotificationRankingUpdate update) { 1022 // protect subclass from concurrent modifications of (@link mNotificationKeys}. 1023 synchronized (mLock) { 1024 applyUpdateLocked(update); 1025 } 1026 isConnected = true; 1027 mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_CONNECTED).sendToTarget(); 1028 } 1029 1030 @Override 1031 public void onNotificationRankingUpdate(NotificationRankingUpdate update) 1032 throws RemoteException { 1033 // protect subclass from concurrent modifications of (@link mNotificationKeys}. 1034 synchronized (mLock) { 1035 applyUpdateLocked(update); 1036 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE, 1037 mRankingMap).sendToTarget(); 1038 } 1039 1040 } 1041 1042 @Override 1043 public void onListenerHintsChanged(int hints) throws RemoteException { 1044 mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_HINTS_CHANGED, 1045 hints, 0).sendToTarget(); 1046 } 1047 1048 @Override 1049 public void onInterruptionFilterChanged(int interruptionFilter) throws RemoteException { 1050 mHandler.obtainMessage(MyHandler.MSG_ON_INTERRUPTION_FILTER_CHANGED, 1051 interruptionFilter, 0).sendToTarget(); 1052 } 1053 1054 @Override 1055 public void onNotificationEnqueued(IStatusBarNotificationHolder notificationHolder, 1056 int importance, boolean user) throws RemoteException { 1057 // no-op in the listener 1058 } 1059 1060 @Override 1061 public void onNotificationVisibilityChanged(String key, long time, boolean visible) 1062 throws RemoteException { 1063 // no-op in the listener 1064 } 1065 1066 @Override 1067 public void onNotificationClick(String key, long time) throws RemoteException { 1068 // no-op in the listener 1069 } 1070 1071 @Override 1072 public void onNotificationActionClick(String key, long time, int actionIndex) 1073 throws RemoteException { 1074 // no-op in the listener 1075 } 1076 } 1077 1078 private void applyUpdateLocked(NotificationRankingUpdate update) { 1079 mRankingMap = new RankingMap(update); 1080 } 1081 1082 /** @hide */ 1083 protected Context getContext() { 1084 if (mSystemContext != null) { 1085 return mSystemContext; 1086 } 1087 return this; 1088 } 1089 1090 /** 1091 * Stores ranking related information on a currently active notification. 1092 * 1093 * <p> 1094 * Ranking objects aren't automatically updated as notification events 1095 * occur. Instead, ranking information has to be retrieved again via the 1096 * current {@link RankingMap}. 1097 */ 1098 public static class Ranking { 1099 1100 /** Value signifying that the user has not expressed a per-app visibility override value. 1101 * @hide */ 1102 public static final int VISIBILITY_NO_OVERRIDE = NotificationManager.VISIBILITY_NO_OVERRIDE; 1103 1104 private String mKey; 1105 private int mRank = -1; 1106 private boolean mIsAmbient; 1107 private boolean mMatchesInterruptionFilter; 1108 private int mVisibilityOverride; 1109 private int mSuppressedVisualEffects; 1110 private @NotificationManager.Importance int mImportance; 1111 private CharSequence mImportanceExplanation; 1112 // System specified group key. 1113 private String mOverrideGroupKey; 1114 1115 public Ranking() {} 1116 1117 /** 1118 * Returns the key of the notification this Ranking applies to. 1119 */ 1120 public String getKey() { 1121 return mKey; 1122 } 1123 1124 /** 1125 * Returns the rank of the notification. 1126 * 1127 * @return the rank of the notification, that is the 0-based index in 1128 * the list of active notifications. 1129 */ 1130 public int getRank() { 1131 return mRank; 1132 } 1133 1134 /** 1135 * Returns whether the notification is an ambient notification, that is 1136 * a notification that doesn't require the user's immediate attention. 1137 */ 1138 public boolean isAmbient() { 1139 return mIsAmbient; 1140 } 1141 1142 /** 1143 * Returns the user specificed visibility for the package that posted 1144 * this notification, or 1145 * {@link NotificationListenerService.Ranking#VISIBILITY_NO_OVERRIDE} if 1146 * no such preference has been expressed. 1147 * @hide 1148 */ 1149 public int getVisibilityOverride() { 1150 return mVisibilityOverride; 1151 } 1152 1153 /** 1154 * Returns the type(s) of visual effects that should be suppressed for this notification. 1155 * See {@link #SUPPRESSED_EFFECT_SCREEN_OFF}, {@link #SUPPRESSED_EFFECT_SCREEN_ON}. 1156 */ 1157 public int getSuppressedVisualEffects() { 1158 return mSuppressedVisualEffects; 1159 } 1160 1161 /** 1162 * Returns whether the notification matches the user's interruption 1163 * filter. 1164 * 1165 * @return {@code true} if the notification is allowed by the filter, or 1166 * {@code false} if it is blocked. 1167 */ 1168 public boolean matchesInterruptionFilter() { 1169 return mMatchesInterruptionFilter; 1170 } 1171 1172 /** 1173 * Returns the importance of the notification, which dictates its 1174 * modes of presentation, see: {@link NotificationManager#IMPORTANCE_DEFAULT}, etc. 1175 * 1176 * @return the rank of the notification 1177 */ 1178 public @NotificationManager.Importance int getImportance() { 1179 return mImportance; 1180 } 1181 1182 /** 1183 * If the importance has been overriden by user preference, then this will be non-null, 1184 * and should be displayed to the user. 1185 * 1186 * @return the explanation for the importance, or null if it is the natural importance 1187 */ 1188 public CharSequence getImportanceExplanation() { 1189 return mImportanceExplanation; 1190 } 1191 1192 /** 1193 * If the system has overriden the group key, then this will be non-null, and this 1194 * key should be used to bundle notifications. 1195 */ 1196 public String getOverrideGroupKey() { 1197 return mOverrideGroupKey; 1198 } 1199 1200 private void populate(String key, int rank, boolean matchesInterruptionFilter, 1201 int visibilityOverride, int suppressedVisualEffects, int importance, 1202 CharSequence explanation, String overrideGroupKey) { 1203 mKey = key; 1204 mRank = rank; 1205 mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW; 1206 mMatchesInterruptionFilter = matchesInterruptionFilter; 1207 mVisibilityOverride = visibilityOverride; 1208 mSuppressedVisualEffects = suppressedVisualEffects; 1209 mImportance = importance; 1210 mImportanceExplanation = explanation; 1211 mOverrideGroupKey = overrideGroupKey; 1212 } 1213 1214 /** 1215 * {@hide} 1216 */ 1217 public static String importanceToString(int importance) { 1218 switch (importance) { 1219 case NotificationManager.IMPORTANCE_UNSPECIFIED: 1220 return "UNSPECIFIED"; 1221 case NotificationManager.IMPORTANCE_NONE: 1222 return "NONE"; 1223 case NotificationManager.IMPORTANCE_MIN: 1224 return "MIN"; 1225 case NotificationManager.IMPORTANCE_LOW: 1226 return "LOW"; 1227 case NotificationManager.IMPORTANCE_DEFAULT: 1228 return "DEFAULT"; 1229 case NotificationManager.IMPORTANCE_HIGH: 1230 case NotificationManager.IMPORTANCE_MAX: 1231 return "HIGH"; 1232 default: 1233 return "UNKNOWN(" + String.valueOf(importance) + ")"; 1234 } 1235 } 1236 } 1237 1238 /** 1239 * Provides access to ranking information on currently active 1240 * notifications. 1241 * 1242 * <p> 1243 * Note that this object represents a ranking snapshot that only applies to 1244 * notifications active at the time of retrieval. 1245 */ 1246 public static class RankingMap implements Parcelable { 1247 private final NotificationRankingUpdate mRankingUpdate; 1248 private ArrayMap<String,Integer> mRanks; 1249 private ArraySet<Object> mIntercepted; 1250 private ArrayMap<String, Integer> mVisibilityOverrides; 1251 private ArrayMap<String, Integer> mSuppressedVisualEffects; 1252 private ArrayMap<String, Integer> mImportance; 1253 private ArrayMap<String, String> mImportanceExplanation; 1254 private ArrayMap<String, String> mOverrideGroupKeys; 1255 1256 private RankingMap(NotificationRankingUpdate rankingUpdate) { 1257 mRankingUpdate = rankingUpdate; 1258 } 1259 1260 /** 1261 * Request the list of notification keys in their current ranking 1262 * order. 1263 * 1264 * @return An array of active notification keys, in their ranking order. 1265 */ 1266 public String[] getOrderedKeys() { 1267 return mRankingUpdate.getOrderedKeys(); 1268 } 1269 1270 /** 1271 * Populates outRanking with ranking information for the notification 1272 * with the given key. 1273 * 1274 * @return true if a valid key has been passed and outRanking has 1275 * been populated; false otherwise 1276 */ 1277 public boolean getRanking(String key, Ranking outRanking) { 1278 int rank = getRank(key); 1279 outRanking.populate(key, rank, !isIntercepted(key), 1280 getVisibilityOverride(key), getSuppressedVisualEffects(key), 1281 getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key)); 1282 return rank >= 0; 1283 } 1284 1285 private int getRank(String key) { 1286 synchronized (this) { 1287 if (mRanks == null) { 1288 buildRanksLocked(); 1289 } 1290 } 1291 Integer rank = mRanks.get(key); 1292 return rank != null ? rank : -1; 1293 } 1294 1295 private boolean isIntercepted(String key) { 1296 synchronized (this) { 1297 if (mIntercepted == null) { 1298 buildInterceptedSetLocked(); 1299 } 1300 } 1301 return mIntercepted.contains(key); 1302 } 1303 1304 private int getVisibilityOverride(String key) { 1305 synchronized (this) { 1306 if (mVisibilityOverrides == null) { 1307 buildVisibilityOverridesLocked(); 1308 } 1309 } 1310 Integer override = mVisibilityOverrides.get(key); 1311 if (override == null) { 1312 return Ranking.VISIBILITY_NO_OVERRIDE; 1313 } 1314 return override.intValue(); 1315 } 1316 1317 private int getSuppressedVisualEffects(String key) { 1318 synchronized (this) { 1319 if (mSuppressedVisualEffects == null) { 1320 buildSuppressedVisualEffectsLocked(); 1321 } 1322 } 1323 Integer suppressed = mSuppressedVisualEffects.get(key); 1324 if (suppressed == null) { 1325 return 0; 1326 } 1327 return suppressed.intValue(); 1328 } 1329 1330 private int getImportance(String key) { 1331 synchronized (this) { 1332 if (mImportance == null) { 1333 buildImportanceLocked(); 1334 } 1335 } 1336 Integer importance = mImportance.get(key); 1337 if (importance == null) { 1338 return NotificationManager.IMPORTANCE_DEFAULT; 1339 } 1340 return importance.intValue(); 1341 } 1342 1343 private String getImportanceExplanation(String key) { 1344 synchronized (this) { 1345 if (mImportanceExplanation == null) { 1346 buildImportanceExplanationLocked(); 1347 } 1348 } 1349 return mImportanceExplanation.get(key); 1350 } 1351 1352 private String getOverrideGroupKey(String key) { 1353 synchronized (this) { 1354 if (mOverrideGroupKeys == null) { 1355 buildOverrideGroupKeys(); 1356 } 1357 } 1358 return mOverrideGroupKeys.get(key); 1359 } 1360 1361 // Locked by 'this' 1362 private void buildRanksLocked() { 1363 String[] orderedKeys = mRankingUpdate.getOrderedKeys(); 1364 mRanks = new ArrayMap<>(orderedKeys.length); 1365 for (int i = 0; i < orderedKeys.length; i++) { 1366 String key = orderedKeys[i]; 1367 mRanks.put(key, i); 1368 } 1369 } 1370 1371 // Locked by 'this' 1372 private void buildInterceptedSetLocked() { 1373 String[] dndInterceptedKeys = mRankingUpdate.getInterceptedKeys(); 1374 mIntercepted = new ArraySet<>(dndInterceptedKeys.length); 1375 Collections.addAll(mIntercepted, dndInterceptedKeys); 1376 } 1377 1378 // Locked by 'this' 1379 private void buildVisibilityOverridesLocked() { 1380 Bundle visibilityBundle = mRankingUpdate.getVisibilityOverrides(); 1381 mVisibilityOverrides = new ArrayMap<>(visibilityBundle.size()); 1382 for (String key: visibilityBundle.keySet()) { 1383 mVisibilityOverrides.put(key, visibilityBundle.getInt(key)); 1384 } 1385 } 1386 1387 // Locked by 'this' 1388 private void buildSuppressedVisualEffectsLocked() { 1389 Bundle suppressedBundle = mRankingUpdate.getSuppressedVisualEffects(); 1390 mSuppressedVisualEffects = new ArrayMap<>(suppressedBundle.size()); 1391 for (String key: suppressedBundle.keySet()) { 1392 mSuppressedVisualEffects.put(key, suppressedBundle.getInt(key)); 1393 } 1394 } 1395 // Locked by 'this' 1396 private void buildImportanceLocked() { 1397 String[] orderedKeys = mRankingUpdate.getOrderedKeys(); 1398 int[] importance = mRankingUpdate.getImportance(); 1399 mImportance = new ArrayMap<>(orderedKeys.length); 1400 for (int i = 0; i < orderedKeys.length; i++) { 1401 String key = orderedKeys[i]; 1402 mImportance.put(key, importance[i]); 1403 } 1404 } 1405 1406 // Locked by 'this' 1407 private void buildImportanceExplanationLocked() { 1408 Bundle explanationBundle = mRankingUpdate.getImportanceExplanation(); 1409 mImportanceExplanation = new ArrayMap<>(explanationBundle.size()); 1410 for (String key: explanationBundle.keySet()) { 1411 mImportanceExplanation.put(key, explanationBundle.getString(key)); 1412 } 1413 } 1414 1415 // Locked by 'this' 1416 private void buildOverrideGroupKeys() { 1417 Bundle overrideGroupKeys = mRankingUpdate.getOverrideGroupKeys(); 1418 mOverrideGroupKeys = new ArrayMap<>(overrideGroupKeys.size()); 1419 for (String key: overrideGroupKeys.keySet()) { 1420 mOverrideGroupKeys.put(key, overrideGroupKeys.getString(key)); 1421 } 1422 } 1423 1424 // ----------- Parcelable 1425 1426 @Override 1427 public int describeContents() { 1428 return 0; 1429 } 1430 1431 @Override 1432 public void writeToParcel(Parcel dest, int flags) { 1433 dest.writeParcelable(mRankingUpdate, flags); 1434 } 1435 1436 public static final Creator<RankingMap> CREATOR = new Creator<RankingMap>() { 1437 @Override 1438 public RankingMap createFromParcel(Parcel source) { 1439 NotificationRankingUpdate rankingUpdate = source.readParcelable(null); 1440 return new RankingMap(rankingUpdate); 1441 } 1442 1443 @Override 1444 public RankingMap[] newArray(int size) { 1445 return new RankingMap[size]; 1446 } 1447 }; 1448 } 1449 1450 private final class MyHandler extends Handler { 1451 public static final int MSG_ON_NOTIFICATION_POSTED = 1; 1452 public static final int MSG_ON_NOTIFICATION_REMOVED = 2; 1453 public static final int MSG_ON_LISTENER_CONNECTED = 3; 1454 public static final int MSG_ON_NOTIFICATION_RANKING_UPDATE = 4; 1455 public static final int MSG_ON_LISTENER_HINTS_CHANGED = 5; 1456 public static final int MSG_ON_INTERRUPTION_FILTER_CHANGED = 6; 1457 1458 public MyHandler(Looper looper) { 1459 super(looper, null, false); 1460 } 1461 1462 @Override 1463 public void handleMessage(Message msg) { 1464 if (!isConnected) { 1465 return; 1466 } 1467 switch (msg.what) { 1468 case MSG_ON_NOTIFICATION_POSTED: { 1469 SomeArgs args = (SomeArgs) msg.obj; 1470 StatusBarNotification sbn = (StatusBarNotification) args.arg1; 1471 RankingMap rankingMap = (RankingMap) args.arg2; 1472 args.recycle(); 1473 onNotificationPosted(sbn, rankingMap); 1474 } break; 1475 1476 case MSG_ON_NOTIFICATION_REMOVED: { 1477 SomeArgs args = (SomeArgs) msg.obj; 1478 StatusBarNotification sbn = (StatusBarNotification) args.arg1; 1479 RankingMap rankingMap = (RankingMap) args.arg2; 1480 int reason = (int) args.arg3; 1481 args.recycle(); 1482 onNotificationRemoved(sbn, rankingMap, reason); 1483 } break; 1484 1485 case MSG_ON_LISTENER_CONNECTED: { 1486 onListenerConnected(); 1487 } break; 1488 1489 case MSG_ON_NOTIFICATION_RANKING_UPDATE: { 1490 RankingMap rankingMap = (RankingMap) msg.obj; 1491 onNotificationRankingUpdate(rankingMap); 1492 } break; 1493 1494 case MSG_ON_LISTENER_HINTS_CHANGED: { 1495 final int hints = msg.arg1; 1496 onListenerHintsChanged(hints); 1497 } break; 1498 1499 case MSG_ON_INTERRUPTION_FILTER_CHANGED: { 1500 final int interruptionFilter = msg.arg1; 1501 onInterruptionFilterChanged(interruptionFilter); 1502 } break; 1503 } 1504 } 1505 } 1506} 1507