NotificationRecord.java revision a344656a010dc3c88aef39109f1ac459792e7607
1/* 2 * Copyright (C) 2014 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 */ 16package com.android.server.notification; 17 18import android.app.Notification; 19import android.content.Context; 20import android.content.pm.PackageManager.NameNotFoundException; 21import android.content.res.Resources; 22import android.graphics.Bitmap; 23import android.service.notification.StatusBarNotification; 24 25import java.io.PrintWriter; 26import java.lang.reflect.Array; 27import java.util.Arrays; 28 29/** 30 * Holds data about notifications that should not be shared with the 31 * {@link android.service.notification.NotificationListenerService}s. 32 * 33 * <p>These objects should not be mutated unless the code is synchronized 34 * on {@link NotificationManagerService#mNotificationList}, and any 35 * modification should be followed by a sorting of that list.</p> 36 * 37 * <p>Is sortable by {@link NotificationComparator}.</p> 38 * 39 * {@hide} 40 */ 41public final class NotificationRecord { 42 final StatusBarNotification sbn; 43 NotificationUsageStats.SingleNotificationStats stats; 44 boolean isCanceled; 45 int score; 46 47 // These members are used by NotificationSignalExtractors 48 // to communicate with the ranking module. 49 private float mContactAffinity; 50 private boolean mRecentlyIntrusive; 51 52 // is this notification currently being intercepted by Zen Mode? 53 private boolean mIntercept; 54 // InterceptedNotifications needs to know if this has been previously evaluated. 55 private boolean mTouchedByZen; 56 57 // Is this record an update of an old record? 58 public boolean isUpdate; 59 60 NotificationRecord(StatusBarNotification sbn, int score) 61 { 62 this.sbn = sbn; 63 this.score = score; 64 } 65 66 // copy any notes that the ranking system may have made before the update 67 public void copyRankingInformation(NotificationRecord previous) { 68 mContactAffinity = previous.mContactAffinity; 69 mRecentlyIntrusive = previous.mRecentlyIntrusive; 70 mTouchedByZen = previous.mTouchedByZen; 71 mIntercept = previous.mIntercept; 72 } 73 74 public Notification getNotification() { return sbn.getNotification(); } 75 public int getFlags() { return sbn.getNotification().flags; } 76 public int getUserId() { return sbn.getUserId(); } 77 public String getKey() { return sbn.getKey(); } 78 79 void dump(PrintWriter pw, String prefix, Context baseContext) { 80 final Notification notification = sbn.getNotification(); 81 pw.println(prefix + this); 82 pw.println(prefix + " uid=" + sbn.getUid() + " userId=" + sbn.getUserId()); 83 pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon) 84 + " / " + idDebugString(baseContext, sbn.getPackageName(), notification.icon)); 85 pw.println(prefix + " pri=" + notification.priority + " score=" + sbn.getScore()); 86 pw.println(prefix + " key=" + sbn.getKey()); 87 pw.println(prefix + " contentIntent=" + notification.contentIntent); 88 pw.println(prefix + " deleteIntent=" + notification.deleteIntent); 89 pw.println(prefix + " tickerText=" + notification.tickerText); 90 pw.println(prefix + " contentView=" + notification.contentView); 91 pw.println(prefix + String.format(" defaults=0x%08x flags=0x%08x", 92 notification.defaults, notification.flags)); 93 pw.println(prefix + " sound=" + notification.sound); 94 pw.println(prefix + String.format(" color=0x%08x", notification.color)); 95 pw.println(prefix + " vibrate=" + Arrays.toString(notification.vibrate)); 96 pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d", 97 notification.ledARGB, notification.ledOnMS, notification.ledOffMS)); 98 if (notification.actions != null && notification.actions.length > 0) { 99 pw.println(prefix + " actions={"); 100 final int N = notification.actions.length; 101 for (int i=0; i<N; i++) { 102 final Notification.Action action = notification.actions[i]; 103 pw.println(String.format("%s [%d] \"%s\" -> %s", 104 prefix, 105 i, 106 action.title, 107 action.actionIntent.toString() 108 )); 109 } 110 pw.println(prefix + " }"); 111 } 112 if (notification.extras != null && notification.extras.size() > 0) { 113 pw.println(prefix + " extras={"); 114 for (String key : notification.extras.keySet()) { 115 pw.print(prefix + " " + key + "="); 116 Object val = notification.extras.get(key); 117 if (val == null) { 118 pw.println("null"); 119 } else { 120 pw.print(val.getClass().getSimpleName()); 121 if (val instanceof CharSequence || val instanceof String) { 122 // redact contents from bugreports 123 } else if (val instanceof Bitmap) { 124 pw.print(String.format(" (%dx%d)", 125 ((Bitmap) val).getWidth(), 126 ((Bitmap) val).getHeight())); 127 } else if (val.getClass().isArray()) { 128 final int N = Array.getLength(val); 129 pw.println(" (" + N + ")"); 130 } else { 131 pw.print(" (" + String.valueOf(val) + ")"); 132 } 133 pw.println(); 134 } 135 } 136 pw.println(prefix + " }"); 137 } 138 pw.println(prefix + " stats=" + stats.toString()); 139 pw.println(prefix + " mContactAffinity=" + mContactAffinity); 140 pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive); 141 pw.println(prefix + " mIntercept=" + mIntercept); 142 } 143 144 145 static String idDebugString(Context baseContext, String packageName, int id) { 146 Context c; 147 148 if (packageName != null) { 149 try { 150 c = baseContext.createPackageContext(packageName, 0); 151 } catch (NameNotFoundException e) { 152 c = baseContext; 153 } 154 } else { 155 c = baseContext; 156 } 157 158 Resources r = c.getResources(); 159 try { 160 return r.getResourceName(id); 161 } catch (Resources.NotFoundException e) { 162 return "<name unknown>"; 163 } 164 } 165 166 @Override 167 public final String toString() { 168 return String.format( 169 "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)", 170 System.identityHashCode(this), 171 this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(), 172 this.sbn.getTag(), this.sbn.getScore(), this.sbn.getKey(), 173 this.sbn.getNotification()); 174 } 175 176 public void setContactAffinity(float contactAffinity) { 177 mContactAffinity = contactAffinity; 178 } 179 180 public float getContactAffinity() { 181 return mContactAffinity; 182 } 183 184 public void setRecentlyIntusive(boolean recentlyIntrusive) { 185 mRecentlyIntrusive = recentlyIntrusive; 186 } 187 188 public boolean isRecentlyIntrusive() { 189 return mRecentlyIntrusive; 190 } 191 192 public boolean setIntercepted(boolean intercept) { 193 mIntercept = intercept; 194 return mIntercept; 195 } 196 197 public boolean isIntercepted() { 198 return mIntercept; 199 } 200 201 public boolean wasTouchedByZen() { 202 return mTouchedByZen; 203 } 204 205 public void setTouchedByZen() { 206 mTouchedByZen = true; 207 } 208 209} 210