NotificationAssistantService.java revision 3aa5f1eec08e6c3233f13935ea45c833433a2d27
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.content.Context; 21import android.content.Intent; 22import android.os.Handler; 23import android.os.IBinder; 24import android.os.Looper; 25import android.os.Message; 26import android.os.RemoteException; 27import android.util.Log; 28import com.android.internal.os.SomeArgs; 29 30import java.util.List; 31 32/** 33 * A service that helps the user manage notifications. 34 */ 35public abstract class NotificationAssistantService extends NotificationListenerService { 36 private static final String TAG = "NotificationAssistants"; 37 38 /** 39 * The {@link Intent} that must be declared as handled by the service. 40 */ 41 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 42 public static final String SERVICE_INTERFACE 43 = "android.service.notification.NotificationAssistantService"; 44 45 private Handler mHandler; 46 47 @Override 48 protected void attachBaseContext(Context base) { 49 super.attachBaseContext(base); 50 mHandler = new MyHandler(getContext().getMainLooper()); 51 } 52 53 @Override 54 public final IBinder onBind(Intent intent) { 55 if (mWrapper == null) { 56 mWrapper = new NotificationAssistantServiceWrapper(); 57 } 58 return mWrapper; 59 } 60 61 /** 62 * A notification was posted by an app. Called before alert. 63 * 64 * @param sbn the new notification 65 * @param importance the initial importance of the notification. 66 * @param user true if the initial importance reflects an explicit user preference. 67 * @return an adjustment or null to take no action, within 100ms. 68 */ 69 abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn, 70 int importance, boolean user); 71 72 /** 73 * Updates a notification. N.B. this won’t cause 74 * an existing notification to alert, but might allow a future update to 75 * this notification to alert. 76 * 77 * @param adjustment the adjustment with an explanation 78 */ 79 public final void adjustNotification(Adjustment adjustment) { 80 if (!isBound()) return; 81 try { 82 getNotificationInterface().applyAdjustmentFromAssistantService(mWrapper, adjustment); 83 } catch (android.os.RemoteException ex) { 84 Log.v(TAG, "Unable to contact notification manager", ex); 85 } 86 } 87 88 /** 89 * Updates existing notifications. Re-ranking won't occur until all adjustments are applied. 90 * N.B. this won’t cause an existing notification to alert, but might allow a future update to 91 * these notifications to alert. 92 * 93 * @param adjustments a list of adjustments with explanations 94 */ 95 public final void adjustNotifications(List<Adjustment> adjustments) { 96 if (!isBound()) return; 97 try { 98 getNotificationInterface().applyAdjustmentsFromAssistantService(mWrapper, adjustments); 99 } catch (android.os.RemoteException ex) { 100 Log.v(TAG, "Unable to contact notification manager", ex); 101 } 102 } 103 104 private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper { 105 @Override 106 public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder, 107 int importance, boolean user) { 108 StatusBarNotification sbn; 109 try { 110 sbn = sbnHolder.get(); 111 } catch (RemoteException e) { 112 Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e); 113 return; 114 } 115 116 SomeArgs args = SomeArgs.obtain(); 117 args.arg1 = sbn; 118 args.argi1 = importance; 119 args.argi2 = user ? 1 : 0; 120 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED, 121 args).sendToTarget(); 122 } 123 } 124 125 private final class MyHandler extends Handler { 126 public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1; 127 128 public MyHandler(Looper looper) { 129 super(looper, null, false); 130 } 131 132 @Override 133 public void handleMessage(Message msg) { 134 switch (msg.what) { 135 case MSG_ON_NOTIFICATION_ENQUEUED: { 136 SomeArgs args = (SomeArgs) msg.obj; 137 StatusBarNotification sbn = (StatusBarNotification) args.arg1; 138 final int importance = args.argi1; 139 final boolean user = args.argi2 == 1; 140 args.recycle(); 141 Adjustment adjustment = onNotificationEnqueued(sbn, importance, user); 142 if (adjustment != null) { 143 adjustNotification(adjustment); 144 } 145 } break; 146 } 147 } 148 } 149} 150