OSDN Git Service

NotificationListenerService API: Avoid unnecessary allocations
authorChristoph Studer <chstuder@google.com>
Thu, 12 Jun 2014 13:25:59 +0000 (15:25 +0200)
committerChristoph Studer <chstuder@google.com>
Thu, 10 Jul 2014 21:37:56 +0000 (21:37 +0000)
Instead of producing Ranking objects, RankingMap just populates
them now, allowing developers to re-use objects and avoid
unnecessary allocations.

Also rename isInterceptedByDnd() to meetsInterruptionFilter(),
since DND is not a concept anymore.

Bug: 15415840
Bug: 16099064
Change-Id: If9861cbdf14593e641a4d4ffd1b967647eb8e2b8

api/current.txt
core/java/android/service/notification/NotificationListenerService.java
core/java/android/service/notification/NotificationRankingUpdate.java
packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
services/core/java/com/android/server/notification/NotificationManagerService.java

index 9d43d58..38e0320 100644 (file)
@@ -26336,16 +26336,17 @@ package android.service.notification {
   }
 
   public static class NotificationListenerService.Ranking {
+    ctor public NotificationListenerService.Ranking();
     method public java.lang.String getKey();
     method public int getRank();
     method public boolean isAmbient();
-    method public boolean isInterceptedByDoNotDisturb();
+    method public boolean meetsInterruptionFilter();
   }
 
   public static class NotificationListenerService.RankingMap implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.String[] getOrderedKeys();
-    method public android.service.notification.NotificationListenerService.Ranking getRanking(java.lang.String);
+    method public boolean getRanking(java.lang.String, android.service.notification.NotificationListenerService.Ranking);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
index 8bd0f4d..7d5ff33 100644 (file)
@@ -29,7 +29,6 @@ import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.util.ArrayMap;
 import android.util.Log;
 
 import java.util.List;
@@ -410,28 +409,20 @@ public abstract class NotificationListenerService extends Service {
     }
 
     /**
-     * Provides access to ranking information on a currently active
-     * notification.
+     * Stores ranking related information on a currently active notification.
      *
      * <p>
-     * Note that this object is not updated on notification events (such as
-     * {@link #onNotificationPosted(StatusBarNotification, RankingMap)},
-     * {@link #onNotificationRemoved(StatusBarNotification)}, etc.). Make sure
-     * to retrieve a new Ranking from the current {@link RankingMap} whenever
-     * a notification event occurs.
+     * Ranking objects aren't automatically updated as notification events
+     * occur. Instead, ranking information has to be retrieved again via the
+     * current {@link RankingMap}.
      */
     public static class Ranking {
-        private final String mKey;
-        private final int mRank;
-        private final boolean mIsAmbient;
-        private final boolean mIsInterceptedByDnd;
+        private String mKey;
+        private int mRank = -1;
+        private boolean mIsAmbient;
+        private boolean mMeetsInterruptionFilter;
 
-        private Ranking(String key, int rank, boolean isAmbient, boolean isInterceptedByDnd) {
-            mKey = key;
-            mRank = rank;
-            mIsAmbient = isAmbient;
-            mIsInterceptedByDnd = isInterceptedByDnd;
-        }
+        public Ranking() {}
 
         /**
          * Returns the key of the notification this Ranking applies to.
@@ -459,11 +450,19 @@ public abstract class NotificationListenerService extends Service {
         }
 
         /**
-         * Returns whether the notification was intercepted by
-         * &quot;Do not disturb&quot;.
+         * Returns whether the notification meets the user's interruption
+         * filter.
          */
-        public boolean isInterceptedByDoNotDisturb() {
-            return mIsInterceptedByDnd;
+        public boolean meetsInterruptionFilter() {
+            return mMeetsInterruptionFilter;
+        }
+
+        private void populate(String key, int rank, boolean isAmbient,
+                boolean meetsInterruptionFilter) {
+            mKey = key;
+            mRank = rank;
+            mIsAmbient = isAmbient;
+            mMeetsInterruptionFilter = meetsInterruptionFilter;
         }
     }
 
@@ -477,12 +476,9 @@ public abstract class NotificationListenerService extends Service {
      */
     public static class RankingMap implements Parcelable {
         private final NotificationRankingUpdate mRankingUpdate;
-        private final ArrayMap<String, Ranking> mRankingCache;
-        private boolean mRankingCacheInitialized;
 
         private RankingMap(NotificationRankingUpdate rankingUpdate) {
             mRankingUpdate = rankingUpdate;
-            mRankingCache = new ArrayMap<>(rankingUpdate.getOrderedKeys().length);
         }
 
         /**
@@ -496,37 +492,42 @@ public abstract class NotificationListenerService extends Service {
         }
 
         /**
-         * Returns the Ranking for the notification with the given key.
+         * Populates outRanking with ranking information for the notification
+         * with the given key.
          *
-         * @return the Ranking of the notification with the given key;
-         *     <code>null</code> when the key is unknown.
+         * @return true if a valid key has been passed and outRanking has
+         *     been populated; false otherwise
          */
-        public Ranking getRanking(String key) {
-            synchronized (mRankingCache) {
-                if (!mRankingCacheInitialized) {
-                    initializeRankingCache();
-                    mRankingCacheInitialized = true;
-                }
-            }
-            return mRankingCache.get(key);
+        public boolean getRanking(String key, Ranking outRanking) {
+            int rank = getRank(key);
+            outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key));
+            return rank >= 0;
         }
 
-        private void initializeRankingCache() {
+        private int getRank(String key) {
+            // TODO: Optimize.
             String[] orderedKeys = mRankingUpdate.getOrderedKeys();
-            int firstAmbientIndex = mRankingUpdate.getFirstAmbientIndex();
             for (int i = 0; i < orderedKeys.length; i++) {
-                String key = orderedKeys[i];
-                boolean isAmbient = firstAmbientIndex > -1 && firstAmbientIndex <= i;
-                boolean isInterceptedByDnd = false;
-                // TODO: Optimize.
-                for (String s : mRankingUpdate.getDndInterceptedKeys()) {
-                    if (s.equals(key)) {
-                        isInterceptedByDnd = true;
-                        break;
-                    }
+                if (orderedKeys[i].equals(key)) {
+                    return i;
                 }
-                mRankingCache.put(key, new Ranking(key, i, isAmbient, isInterceptedByDnd));
             }
+            return -1;
+        }
+
+        private boolean isAmbient(String key) {
+            int rank = getRank(key);
+            return rank >= 0 && rank >= mRankingUpdate.getFirstAmbientIndex();
+        }
+
+        private boolean isIntercepted(String key) {
+            // TODO: Optimize.
+            for (String interceptedKey : mRankingUpdate.getInterceptedKeys()) {
+                if (interceptedKey.equals(key)) {
+                    return true;
+                }
+            }
+            return false;
         }
 
         // ----------- Parcelable
index 4b13d95..26af38b 100644 (file)
@@ -24,20 +24,20 @@ import android.os.Parcelable;
 public class NotificationRankingUpdate implements Parcelable {
     // TODO: Support incremental updates.
     private final String[] mKeys;
-    private final String[] mDndInterceptedKeys;
+    private final String[] mInterceptedKeys;
     private final int mFirstAmbientIndex;
 
-    public NotificationRankingUpdate(String[] keys, String[] dndInterceptedKeys,
+    public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
                                      int firstAmbientIndex) {
         mKeys = keys;
         mFirstAmbientIndex = firstAmbientIndex;
-        mDndInterceptedKeys = dndInterceptedKeys;
+        mInterceptedKeys = interceptedKeys;
     }
 
     public NotificationRankingUpdate(Parcel in) {
         mKeys = in.readStringArray();
         mFirstAmbientIndex = in.readInt();
-        mDndInterceptedKeys = in.readStringArray();
+        mInterceptedKeys = in.readStringArray();
     }
 
     @Override
@@ -49,7 +49,7 @@ public class NotificationRankingUpdate implements Parcelable {
     public void writeToParcel(Parcel out, int flags) {
         out.writeStringArray(mKeys);
         out.writeInt(mFirstAmbientIndex);
-        out.writeStringArray(mDndInterceptedKeys);
+        out.writeStringArray(mInterceptedKeys);
     }
 
     public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -71,7 +71,7 @@ public class NotificationRankingUpdate implements Parcelable {
         return mFirstAmbientIndex;
     }
 
-    public String[] getDndInterceptedKeys() {
-        return mDndInterceptedKeys;
+    public String[] getInterceptedKeys() {
+        return mInterceptedKeys;
     }
 }
index 9921c55..ed3ebf5 100644 (file)
@@ -75,16 +75,18 @@ public class NotificationData {
     }
 
     private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
-    private RankingMap mRanking;
+    private RankingMap mRankingMap;
+    private final Ranking mTmpRanking = new Ranking();
     private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() {
+        private final Ranking mRankingA = new Ranking();
+        private final Ranking mRankingB = new Ranking();
+
         @Override
         public int compare(Entry a, Entry b) {
-            if (mRanking != null) {
-                Ranking aRanking = mRanking.getRanking(a.key);
-                Ranking bRanking = mRanking.getRanking(b.key);
-                int aRank = aRanking != null ? aRanking.getRank() : -1;
-                int bRank = bRanking != null ? bRanking.getRank() : -1;
-                return aRank - bRank;
+            if (mRankingMap != null) {
+                mRankingMap.getRanking(a.key, mRankingA);
+                mRankingMap.getRanking(b.key, mRankingB);
+                return mRankingA.getRank() - mRankingB.getRank();
             }
 
             final StatusBarNotification na = a.notification;
@@ -138,7 +140,7 @@ public class NotificationData {
 
     public boolean isAmbient(String key) {
         // TODO: Remove when switching to NotificationListener.
-        if (mRanking == null) {
+        if (mRankingMap == null) {
             for (Entry entry : mEntries) {
                 if (key.equals(entry.key)) {
                     return entry.notification.getNotification().priority ==
@@ -146,15 +148,15 @@ public class NotificationData {
                 }
             }
         } else {
-            Ranking ranking = mRanking.getRanking(key);
-            return ranking != null && ranking.isAmbient();
+            mRankingMap.getRanking(key, mTmpRanking);
+            return mTmpRanking.isAmbient();
         }
         return false;
     }
 
     private void updateRankingAndSort(RankingMap ranking) {
         if (ranking != null) {
-            mRanking = ranking;
+            mRankingMap = ranking;
         }
         Collections.sort(mEntries, mRankingComparator);
     }
index 3a6cec2..892f61f 100644 (file)
@@ -2301,7 +2301,7 @@ public class NotificationManagerService extends SystemService {
         int speedBumpIndex = -1;
         final int N = mNotificationList.size();
         ArrayList<String> keys = new ArrayList<String>(N);
-        ArrayList<String> dndKeys = new ArrayList<String>(N);
+        ArrayList<String> interceptedKeys = new ArrayList<String>(N);
         for (int i = 0; i < N; i++) {
             NotificationRecord record = mNotificationList.get(i);
             if (!info.enabledAndUserMatches(record.sbn.getUserId())) {
@@ -2309,7 +2309,7 @@ public class NotificationManagerService extends SystemService {
             }
             keys.add(record.sbn.getKey());
             if (record.isIntercepted()) {
-                dndKeys.add(record.sbn.getKey());
+                interceptedKeys.add(record.sbn.getKey());
             }
             if (speedBumpIndex == -1 &&
                     record.sbn.getNotification().priority == Notification.PRIORITY_MIN) {
@@ -2317,8 +2317,8 @@ public class NotificationManagerService extends SystemService {
             }
         }
         String[] keysAr = keys.toArray(new String[keys.size()]);
-        String[] dndKeysAr = dndKeys.toArray(new String[dndKeys.size()]);
-        return new NotificationRankingUpdate(keysAr, dndKeysAr, speedBumpIndex);
+        String[] interceptedKeysAr = interceptedKeys.toArray(new String[interceptedKeys.size()]);
+        return new NotificationRankingUpdate(keysAr, interceptedKeysAr, speedBumpIndex);
     }
 
     public class NotificationListeners extends ManagedServices {