NotificationAssistantService.java revision c441856bb6c5712efab9d5ef422c95210884a1d8
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.service.notification; 18 19import android.annotation.SdkConstant; 20import android.annotation.SystemApi; 21import android.app.INotificationManager; 22import android.app.Notification; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.Intent; 26import android.net.Uri; 27import android.os.IBinder; 28import android.os.Parcel; 29import android.os.Parcelable; 30import android.os.RemoteException; 31import android.os.ServiceManager; 32import android.util.Log; 33 34/** 35 * A service that helps the user manage notifications by modifying the 36 * relative importance of notifications. 37 * <p>To extend this class, you must declare the service in your manifest file with 38 * the {@link android.Manifest.permission#BIND_NOTIFICATION_ASSISTANT_SERVICE} permission 39 * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p> 40 * <pre> 41 * <service android:name=".NotificationAssistant" 42 * android:label="@string/service_name" 43 * android:permission="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"> 44 * <intent-filter> 45 * <action android:name="android.service.notification.NotificationAssistantService" /> 46 * </intent-filter> 47 * </service></pre> 48 * @hide 49 */ 50@SystemApi 51public abstract class NotificationAssistantService extends NotificationListenerService { 52 private static final String TAG = "NotificationAssistant"; 53 54 /** 55 * The {@link Intent} that must be declared as handled by the service. 56 */ 57 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 58 public static final String SERVICE_INTERFACE 59 = "android.service.notification.NotificationAssistantService"; 60 61 /** Notification was canceled by the status bar reporting a click. */ 62 public static final int REASON_DELEGATE_CLICK = 1; 63 64 /** Notification was canceled by the status bar reporting a user dismissal. */ 65 public static final int REASON_DELEGATE_CANCEL = 2; 66 67 /** Notification was canceled by the status bar reporting a user dismiss all. */ 68 public static final int REASON_DELEGATE_CANCEL_ALL = 3; 69 70 /** Notification was canceled by the status bar reporting an inflation error. */ 71 public static final int REASON_DELEGATE_ERROR = 4; 72 73 /** Notification was canceled by the package manager modifying the package. */ 74 public static final int REASON_PACKAGE_CHANGED = 5; 75 76 /** Notification was canceled by the owning user context being stopped. */ 77 public static final int REASON_USER_STOPPED = 6; 78 79 /** Notification was canceled by the user banning the package. */ 80 public static final int REASON_PACKAGE_BANNED = 7; 81 82 /** Notification was canceled by the app canceling this specific notification. */ 83 public static final int REASON_APP_CANCEL = 8; 84 85 /** Notification was canceled by the app cancelling all its notifications. */ 86 public static final int REASON_APP_CANCEL_ALL = 9; 87 88 /** Notification was canceled by a listener reporting a user dismissal. */ 89 public static final int REASON_LISTENER_CANCEL = 10; 90 91 /** Notification was canceled by a listener reporting a user dismiss all. */ 92 public static final int REASON_LISTENER_CANCEL_ALL = 11; 93 94 /** Notification was canceled because it was a member of a canceled group. */ 95 public static final int REASON_GROUP_SUMMARY_CANCELED = 12; 96 97 /** Notification was canceled because it was an invisible member of a group. */ 98 public static final int REASON_GROUP_OPTIMIZATION = 13; 99 100 /** Notification was canceled by the user banning the topic. */ 101 public static final int REASON_TOPIC_BANNED = 14; 102 103 /** Notification was canceled by the device administrator suspending the package. */ 104 public static final int REASON_PACKAGE_SUSPENDED = 15; 105 106 /** Notification was canceled by the owning managed profile being turned off. */ 107 public static final int REASON_PROFILE_TURNED_OFF = 16; 108 109 public class Adjustment { 110 int mImportance; 111 CharSequence mExplanation; 112 Uri mReference; 113 114 /** 115 * Create a notification importance adjustment. 116 * 117 * @param importance The final importance of the notification. 118 * @param explanation A human-readable justification for the adjustment. 119 * @param reference A reference to an external object that augments the 120 * explanation, such as a 121 * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}, 122 * or null. 123 */ 124 public Adjustment(int importance, CharSequence explanation, Uri reference) { 125 mImportance = importance; 126 mExplanation = explanation; 127 mReference = reference; 128 } 129 } 130 131 @Override 132 public IBinder onBind(Intent intent) { 133 if (mWrapper == null) { 134 mWrapper = new NotificationAssistantWrapper(); 135 } 136 return mWrapper; 137 } 138 139 /** 140 * A notification was posted by an app. Called before alert. 141 * 142 * @param sbn the new notification 143 * @param importance the initial importance of the notification. 144 * @param user true if the initial importance reflects an explicit user preference. 145 * @return an adjustment or null to take no action, within 100ms. 146 */ 147 abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn, 148 int importance, boolean user); 149 150 /** 151 * The visibility of a notification has changed. 152 * 153 * @param key the notification key 154 * @param time milliseconds since midnight, January 1, 1970 UTC. 155 * @param visible true if the notification became visible, false if hidden. 156 */ 157 public void onNotificationVisibilityChanged(String key, long time, boolean visible) 158 { 159 // Do nothing, Override this to collect visibility statistics. 160 } 161 162 /** 163 * The user clicked on a notification. 164 * 165 * @param key the notification key 166 * @param time milliseconds since midnight, January 1, 1970 UTC. 167 */ 168 public void onNotificationClick(String key, long time) 169 { 170 // Do nothing, Override this to collect click statistics 171 } 172 173 /** 174 * The user clicked on a notification action. 175 * 176 * @param key the notification key 177 * @param time milliseconds since midnight, January 1, 1970 UTC. 178 * @param actionIndex the index of the action button that was pressed. 179 */ 180 public void onNotificationActionClick(String key, long time, int actionIndex) 181 { 182 // Do nothing, Override this to collect action button click statistics 183 } 184 185 /** 186 * A notification was removed. 187 188 * @param key the notification key 189 * @param time milliseconds since midnight, January 1, 1970 UTC. 190 * @param reason see {@link #REASON_LISTENER_CANCEL}, etc. 191 */ 192 public void onNotificationRemoved(String key, long time, int reason) { 193 // Do nothing, Override this to collect dismissal statistics 194 } 195 196 /** 197 * Change the importance of an existing notification. N.B. this won’t cause 198 * an existing notification to alert, but might allow a future update to 199 * this notification to alert. 200 * 201 * @param key the notification key 202 * @param adjustment the new importance with an explanation 203 */ 204 public final void adjustImportance(String key, Adjustment adjustment) 205 { 206 if (!isBound()) return; 207 try { 208 getNotificationInterface().setImportanceFromAssistant(mWrapper, key, 209 adjustment.mImportance, adjustment.mExplanation); 210 } catch (android.os.RemoteException ex) { 211 Log.v(TAG, "Unable to contact notification manager", ex); 212 } 213 } 214 215 private class NotificationAssistantWrapper extends NotificationListenerWrapper { 216 @Override 217 public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder, 218 int importance, boolean user) throws RemoteException { 219 StatusBarNotification sbn; 220 try { 221 sbn = sbnHolder.get(); 222 } catch (RemoteException e) { 223 Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e); 224 return; 225 } 226 227 try { 228 Adjustment adjustment = 229 NotificationAssistantService.this.onNotificationEnqueued(sbn, importance, user); 230 if (adjustment != null) { 231 adjustImportance(sbn.getKey(), adjustment); 232 } 233 } catch (Throwable t) { 234 Log.w(TAG, "Error running onNotificationEnqueued", t); 235 } 236 } 237 238 @Override 239 public void onNotificationVisibilityChanged(String key, long time, boolean visible) 240 throws RemoteException { 241 try { 242 NotificationAssistantService.this.onNotificationVisibilityChanged(key, time, 243 visible); 244 } catch (Throwable t) { 245 Log.w(TAG, "Error running onNotificationVisibilityChanged", t); 246 } 247 } 248 249 @Override 250 public void onNotificationClick(String key, long time) throws RemoteException { 251 try { 252 NotificationAssistantService.this.onNotificationClick(key, time); 253 } catch (Throwable t) { 254 Log.w(TAG, "Error running onNotificationClick", t); 255 } 256 } 257 258 @Override 259 public void onNotificationActionClick(String key, long time, int actionIndex) 260 throws RemoteException { 261 try { 262 NotificationAssistantService.this.onNotificationActionClick(key, time, actionIndex); 263 } catch (Throwable t) { 264 Log.w(TAG, "Error running onNotificationActionClick", t); 265 } 266 } 267 268 @Override 269 public void onNotificationRemovedReason(String key, long time, int reason) 270 throws RemoteException { 271 try { 272 NotificationAssistantService.this.onNotificationRemoved(key, time, reason); 273 } catch (Throwable t) { 274 Log.w(TAG, "Error running onNotificationRemoved", t); 275 } 276 } 277 } 278} 279