154bbef435ed857fc68941672799fc8001c101119Chris Wren/** 254bbef435ed857fc68941672799fc8001c101119Chris Wren * Copyright (c) 2014, The Android Open Source Project 354bbef435ed857fc68941672799fc8001c101119Chris Wren * 454bbef435ed857fc68941672799fc8001c101119Chris Wren * Licensed under the Apache License, Version 2.0 (the "License"); 554bbef435ed857fc68941672799fc8001c101119Chris Wren * you may not use this file except in compliance with the License. 654bbef435ed857fc68941672799fc8001c101119Chris Wren * You may obtain a copy of the License at 754bbef435ed857fc68941672799fc8001c101119Chris Wren * 854bbef435ed857fc68941672799fc8001c101119Chris Wren * http://www.apache.org/licenses/LICENSE-2.0 954bbef435ed857fc68941672799fc8001c101119Chris Wren * 1054bbef435ed857fc68941672799fc8001c101119Chris Wren * Unless required by applicable law or agreed to in writing, software 1154bbef435ed857fc68941672799fc8001c101119Chris Wren * distributed under the License is distributed on an "AS IS" BASIS, 1254bbef435ed857fc68941672799fc8001c101119Chris Wren * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1354bbef435ed857fc68941672799fc8001c101119Chris Wren * See the License for the specific language governing permissions and 1454bbef435ed857fc68941672799fc8001c101119Chris Wren * limitations under the License. 1554bbef435ed857fc68941672799fc8001c101119Chris Wren */ 1654bbef435ed857fc68941672799fc8001c101119Chris Wrenpackage com.android.server.notification; 1754bbef435ed857fc68941672799fc8001c101119Chris Wren 1854bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.app.Notification; 1954bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.content.Context; 2054bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.os.Handler; 2154bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.os.Message; 2254bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.os.UserHandle; 233ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wrenimport android.service.notification.NotificationListenerService; 2454bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.text.TextUtils; 2554bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.util.ArrayMap; 263ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wrenimport android.util.ArraySet; 27cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studerimport android.util.Log; 2854bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.util.Slog; 2954bbef435ed857fc68941672799fc8001c101119Chris Wrenimport android.util.SparseIntArray; 3054bbef435ed857fc68941672799fc8001c101119Chris Wrenimport org.xmlpull.v1.XmlPullParser; 3154bbef435ed857fc68941672799fc8001c101119Chris Wrenimport org.xmlpull.v1.XmlPullParserException; 3254bbef435ed857fc68941672799fc8001c101119Chris Wrenimport org.xmlpull.v1.XmlSerializer; 3354bbef435ed857fc68941672799fc8001c101119Chris Wren 3454bbef435ed857fc68941672799fc8001c101119Chris Wrenimport java.io.IOException; 3554bbef435ed857fc68941672799fc8001c101119Chris Wrenimport java.io.PrintWriter; 3654bbef435ed857fc68941672799fc8001c101119Chris Wrenimport java.util.ArrayList; 3754bbef435ed857fc68941672799fc8001c101119Chris Wrenimport java.util.Collections; 383ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wrenimport java.util.Set; 3954bbef435ed857fc68941672799fc8001c101119Chris Wrenimport java.util.concurrent.TimeUnit; 4054bbef435ed857fc68941672799fc8001c101119Chris Wren 4154bbef435ed857fc68941672799fc8001c101119Chris Wrenpublic class RankingHelper implements RankingConfig { 4254bbef435ed857fc68941672799fc8001c101119Chris Wren private static final String TAG = "RankingHelper"; 4354bbef435ed857fc68941672799fc8001c101119Chris Wren private static final boolean DEBUG = false; 4454bbef435ed857fc68941672799fc8001c101119Chris Wren 4554bbef435ed857fc68941672799fc8001c101119Chris Wren private static final int XML_VERSION = 1; 4654bbef435ed857fc68941672799fc8001c101119Chris Wren 4754bbef435ed857fc68941672799fc8001c101119Chris Wren private static final String TAG_RANKING = "ranking"; 4854bbef435ed857fc68941672799fc8001c101119Chris Wren private static final String TAG_PACKAGE = "package"; 4954bbef435ed857fc68941672799fc8001c101119Chris Wren private static final String ATT_VERSION = "version"; 5054bbef435ed857fc68941672799fc8001c101119Chris Wren 5154bbef435ed857fc68941672799fc8001c101119Chris Wren private static final String ATT_NAME = "name"; 5254bbef435ed857fc68941672799fc8001c101119Chris Wren private static final String ATT_UID = "uid"; 5354bbef435ed857fc68941672799fc8001c101119Chris Wren private static final String ATT_PRIORITY = "priority"; 543ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren private static final String ATT_VISIBILITY = "visibility"; 5554bbef435ed857fc68941672799fc8001c101119Chris Wren 5654bbef435ed857fc68941672799fc8001c101119Chris Wren private final NotificationSignalExtractor[] mSignalExtractors; 571031c974855ff4117a6d7866e664295786840319Chris Wren private final NotificationComparator mPreliminaryComparator = new NotificationComparator(); 58cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer private final GlobalSortKeyComparator mFinalComparator = new GlobalSortKeyComparator(); 5954bbef435ed857fc68941672799fc8001c101119Chris Wren 6054bbef435ed857fc68941672799fc8001c101119Chris Wren // Package name to uid, to priority. Would be better as Table<String, Int, Int> 6154bbef435ed857fc68941672799fc8001c101119Chris Wren private final ArrayMap<String, SparseIntArray> mPackagePriorities; 623ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren private final ArrayMap<String, SparseIntArray> mPackageVisibilities; 631031c974855ff4117a6d7866e664295786840319Chris Wren private final ArrayMap<String, NotificationRecord> mProxyByGroupTmp; 6454bbef435ed857fc68941672799fc8001c101119Chris Wren 6554bbef435ed857fc68941672799fc8001c101119Chris Wren private final Context mContext; 6654bbef435ed857fc68941672799fc8001c101119Chris Wren private final Handler mRankingHandler; 6754bbef435ed857fc68941672799fc8001c101119Chris Wren 6854bbef435ed857fc68941672799fc8001c101119Chris Wren public RankingHelper(Context context, Handler rankingHandler, String[] extractorNames) { 6954bbef435ed857fc68941672799fc8001c101119Chris Wren mContext = context; 7054bbef435ed857fc68941672799fc8001c101119Chris Wren mRankingHandler = rankingHandler; 7154bbef435ed857fc68941672799fc8001c101119Chris Wren mPackagePriorities = new ArrayMap<String, SparseIntArray>(); 723ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren mPackageVisibilities = new ArrayMap<String, SparseIntArray>(); 7354bbef435ed857fc68941672799fc8001c101119Chris Wren 7454bbef435ed857fc68941672799fc8001c101119Chris Wren final int N = extractorNames.length; 7554bbef435ed857fc68941672799fc8001c101119Chris Wren mSignalExtractors = new NotificationSignalExtractor[N]; 7654bbef435ed857fc68941672799fc8001c101119Chris Wren for (int i = 0; i < N; i++) { 7754bbef435ed857fc68941672799fc8001c101119Chris Wren try { 7854bbef435ed857fc68941672799fc8001c101119Chris Wren Class<?> extractorClass = mContext.getClassLoader().loadClass(extractorNames[i]); 7954bbef435ed857fc68941672799fc8001c101119Chris Wren NotificationSignalExtractor extractor = 8054bbef435ed857fc68941672799fc8001c101119Chris Wren (NotificationSignalExtractor) extractorClass.newInstance(); 8154bbef435ed857fc68941672799fc8001c101119Chris Wren extractor.initialize(mContext); 8254bbef435ed857fc68941672799fc8001c101119Chris Wren extractor.setConfig(this); 8354bbef435ed857fc68941672799fc8001c101119Chris Wren mSignalExtractors[i] = extractor; 8454bbef435ed857fc68941672799fc8001c101119Chris Wren } catch (ClassNotFoundException e) { 8554bbef435ed857fc68941672799fc8001c101119Chris Wren Slog.w(TAG, "Couldn't find extractor " + extractorNames[i] + ".", e); 8654bbef435ed857fc68941672799fc8001c101119Chris Wren } catch (InstantiationException e) { 8754bbef435ed857fc68941672799fc8001c101119Chris Wren Slog.w(TAG, "Couldn't instantiate extractor " + extractorNames[i] + ".", e); 8854bbef435ed857fc68941672799fc8001c101119Chris Wren } catch (IllegalAccessException e) { 8954bbef435ed857fc68941672799fc8001c101119Chris Wren Slog.w(TAG, "Problem accessing extractor " + extractorNames[i] + ".", e); 9054bbef435ed857fc68941672799fc8001c101119Chris Wren } 9154bbef435ed857fc68941672799fc8001c101119Chris Wren } 921031c974855ff4117a6d7866e664295786840319Chris Wren mProxyByGroupTmp = new ArrayMap<String, NotificationRecord>(); 9354bbef435ed857fc68941672799fc8001c101119Chris Wren } 9454bbef435ed857fc68941672799fc8001c101119Chris Wren 952b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock public <T extends NotificationSignalExtractor> T findExtractor(Class<T> extractorClass) { 962b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock final int N = mSignalExtractors.length; 972b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock for (int i = 0; i < N; i++) { 982b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock final NotificationSignalExtractor extractor = mSignalExtractors[i]; 992b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock if (extractorClass.equals(extractor.getClass())) { 1002b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock return (T) extractor; 1012b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock } 1022b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock } 1032b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock return null; 1042b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock } 1052b122f4c2e691f0319e4f9ea5873989792bb56a6John Spurlock 10654bbef435ed857fc68941672799fc8001c101119Chris Wren public void extractSignals(NotificationRecord r) { 10754bbef435ed857fc68941672799fc8001c101119Chris Wren final int N = mSignalExtractors.length; 10854bbef435ed857fc68941672799fc8001c101119Chris Wren for (int i = 0; i < N; i++) { 10954bbef435ed857fc68941672799fc8001c101119Chris Wren NotificationSignalExtractor extractor = mSignalExtractors[i]; 11054bbef435ed857fc68941672799fc8001c101119Chris Wren try { 11154bbef435ed857fc68941672799fc8001c101119Chris Wren RankingReconsideration recon = extractor.process(r); 11254bbef435ed857fc68941672799fc8001c101119Chris Wren if (recon != null) { 11354bbef435ed857fc68941672799fc8001c101119Chris Wren Message m = Message.obtain(mRankingHandler, 11454bbef435ed857fc68941672799fc8001c101119Chris Wren NotificationManagerService.MESSAGE_RECONSIDER_RANKING, recon); 11554bbef435ed857fc68941672799fc8001c101119Chris Wren long delay = recon.getDelay(TimeUnit.MILLISECONDS); 11654bbef435ed857fc68941672799fc8001c101119Chris Wren mRankingHandler.sendMessageDelayed(m, delay); 11754bbef435ed857fc68941672799fc8001c101119Chris Wren } 11854bbef435ed857fc68941672799fc8001c101119Chris Wren } catch (Throwable t) { 11954bbef435ed857fc68941672799fc8001c101119Chris Wren Slog.w(TAG, "NotificationSignalExtractor failed.", t); 12054bbef435ed857fc68941672799fc8001c101119Chris Wren } 12154bbef435ed857fc68941672799fc8001c101119Chris Wren } 12254bbef435ed857fc68941672799fc8001c101119Chris Wren } 12354bbef435ed857fc68941672799fc8001c101119Chris Wren 12454bbef435ed857fc68941672799fc8001c101119Chris Wren public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException { 12554bbef435ed857fc68941672799fc8001c101119Chris Wren int type = parser.getEventType(); 12654bbef435ed857fc68941672799fc8001c101119Chris Wren if (type != XmlPullParser.START_TAG) return; 12754bbef435ed857fc68941672799fc8001c101119Chris Wren String tag = parser.getName(); 12854bbef435ed857fc68941672799fc8001c101119Chris Wren if (!TAG_RANKING.equals(tag)) return; 12954bbef435ed857fc68941672799fc8001c101119Chris Wren mPackagePriorities.clear(); 13054bbef435ed857fc68941672799fc8001c101119Chris Wren final int version = safeInt(parser, ATT_VERSION, XML_VERSION); 13154bbef435ed857fc68941672799fc8001c101119Chris Wren while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 13254bbef435ed857fc68941672799fc8001c101119Chris Wren tag = parser.getName(); 13354bbef435ed857fc68941672799fc8001c101119Chris Wren if (type == XmlPullParser.END_TAG && TAG_RANKING.equals(tag)) { 13454bbef435ed857fc68941672799fc8001c101119Chris Wren return; 13554bbef435ed857fc68941672799fc8001c101119Chris Wren } 13654bbef435ed857fc68941672799fc8001c101119Chris Wren if (type == XmlPullParser.START_TAG) { 13754bbef435ed857fc68941672799fc8001c101119Chris Wren if (TAG_PACKAGE.equals(tag)) { 13854bbef435ed857fc68941672799fc8001c101119Chris Wren int uid = safeInt(parser, ATT_UID, UserHandle.USER_ALL); 13954bbef435ed857fc68941672799fc8001c101119Chris Wren int priority = safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT); 1403ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren int vis = safeInt(parser, ATT_VISIBILITY, 1413ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE); 14254bbef435ed857fc68941672799fc8001c101119Chris Wren String name = parser.getAttributeValue(null, ATT_NAME); 14354bbef435ed857fc68941672799fc8001c101119Chris Wren 1443ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (!TextUtils.isEmpty(name)) { 1453ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (priority != Notification.PRIORITY_DEFAULT) { 1463ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren SparseIntArray priorityByUid = mPackagePriorities.get(name); 1473ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (priorityByUid == null) { 1483ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren priorityByUid = new SparseIntArray(); 1493ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren mPackagePriorities.put(name, priorityByUid); 1503ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 1513ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren priorityByUid.put(uid, priority); 1523ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 1533ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (vis != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) { 1543ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren SparseIntArray visibilityByUid = mPackageVisibilities.get(name); 1553ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (visibilityByUid == null) { 1563ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren visibilityByUid = new SparseIntArray(); 1573ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren mPackageVisibilities.put(name, visibilityByUid); 1583ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 1593ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren visibilityByUid.put(uid, vis); 16054bbef435ed857fc68941672799fc8001c101119Chris Wren } 16154bbef435ed857fc68941672799fc8001c101119Chris Wren } 16254bbef435ed857fc68941672799fc8001c101119Chris Wren } 16354bbef435ed857fc68941672799fc8001c101119Chris Wren } 16454bbef435ed857fc68941672799fc8001c101119Chris Wren } 16554bbef435ed857fc68941672799fc8001c101119Chris Wren throw new IllegalStateException("Failed to reach END_DOCUMENT"); 16654bbef435ed857fc68941672799fc8001c101119Chris Wren } 16754bbef435ed857fc68941672799fc8001c101119Chris Wren 16854bbef435ed857fc68941672799fc8001c101119Chris Wren public void writeXml(XmlSerializer out) throws IOException { 16954bbef435ed857fc68941672799fc8001c101119Chris Wren out.startTag(null, TAG_RANKING); 17054bbef435ed857fc68941672799fc8001c101119Chris Wren out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION)); 17154bbef435ed857fc68941672799fc8001c101119Chris Wren 1723ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren final Set<String> packageNames = new ArraySet<>(mPackagePriorities.size() 1733ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren + mPackageVisibilities.size()); 1743ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren packageNames.addAll(mPackagePriorities.keySet()); 1753ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren packageNames.addAll(mPackageVisibilities.keySet()); 1763ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren final Set<Integer> packageUids = new ArraySet<>(); 1773ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren for (String packageName : packageNames) { 1783ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren packageUids.clear(); 1793ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren SparseIntArray priorityByUid = mPackagePriorities.get(packageName); 1803ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName); 1813ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (priorityByUid != null) { 1823ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren final int M = priorityByUid.size(); 1833ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren for (int j = 0; j < M; j++) { 1843ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren packageUids.add(priorityByUid.keyAt(j)); 1853ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 1863ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 1873ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (visibilityByUid != null) { 1883ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren final int M = visibilityByUid.size(); 1893ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren for (int j = 0; j < M; j++) { 1903ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren packageUids.add(visibilityByUid.keyAt(j)); 1913ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 1923ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 1933ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren for (Integer uid : packageUids) { 19454bbef435ed857fc68941672799fc8001c101119Chris Wren out.startTag(null, TAG_PACKAGE); 1953ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren out.attribute(null, ATT_NAME, packageName); 1963ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (priorityByUid != null) { 1973ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren final int priority = priorityByUid.get(uid); 1983ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (priority != Notification.PRIORITY_DEFAULT) { 1993ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren out.attribute(null, ATT_PRIORITY, Integer.toString(priority)); 2003ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 2013ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 2023ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (visibilityByUid != null) { 2033ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren final int visibility = visibilityByUid.get(uid); 2043ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (visibility != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) { 2053ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren out.attribute(null, ATT_VISIBILITY, Integer.toString(visibility)); 2063ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 2073ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 20854bbef435ed857fc68941672799fc8001c101119Chris Wren out.attribute(null, ATT_UID, Integer.toString(uid)); 20954bbef435ed857fc68941672799fc8001c101119Chris Wren out.endTag(null, TAG_PACKAGE); 21054bbef435ed857fc68941672799fc8001c101119Chris Wren } 21154bbef435ed857fc68941672799fc8001c101119Chris Wren } 21254bbef435ed857fc68941672799fc8001c101119Chris Wren out.endTag(null, TAG_RANKING); 21354bbef435ed857fc68941672799fc8001c101119Chris Wren } 21454bbef435ed857fc68941672799fc8001c101119Chris Wren 21554bbef435ed857fc68941672799fc8001c101119Chris Wren private void updateConfig() { 21654bbef435ed857fc68941672799fc8001c101119Chris Wren final int N = mSignalExtractors.length; 21754bbef435ed857fc68941672799fc8001c101119Chris Wren for (int i = 0; i < N; i++) { 21854bbef435ed857fc68941672799fc8001c101119Chris Wren mSignalExtractors[i].setConfig(this); 21954bbef435ed857fc68941672799fc8001c101119Chris Wren } 22054bbef435ed857fc68941672799fc8001c101119Chris Wren mRankingHandler.sendEmptyMessage(NotificationManagerService.MESSAGE_RANKING_CONFIG_CHANGE); 22154bbef435ed857fc68941672799fc8001c101119Chris Wren } 22254bbef435ed857fc68941672799fc8001c101119Chris Wren 22354bbef435ed857fc68941672799fc8001c101119Chris Wren public void sort(ArrayList<NotificationRecord> notificationList) { 2241031c974855ff4117a6d7866e664295786840319Chris Wren final int N = notificationList.size(); 225cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // clear global sort keys 2261031c974855ff4117a6d7866e664295786840319Chris Wren for (int i = N - 1; i >= 0; i--) { 227cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer notificationList.get(i).setGlobalSortKey(null); 2281031c974855ff4117a6d7866e664295786840319Chris Wren } 2291031c974855ff4117a6d7866e664295786840319Chris Wren 23085374052e3c359884b7a54266666243d049dca7eChristoph Studer // rank each record individually 23185374052e3c359884b7a54266666243d049dca7eChristoph Studer Collections.sort(notificationList, mPreliminaryComparator); 232cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer 233cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer synchronized (mProxyByGroupTmp) { 234cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // record individual ranking result and nominate proxies for each group 235cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer for (int i = N - 1; i >= 0; i--) { 236cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer final NotificationRecord record = notificationList.get(i); 237cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer record.setAuthoritativeRank(i); 238cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer final String groupKey = record.getGroupKey(); 239cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer boolean isGroupSummary = record.getNotification().isGroupSummary(); 240cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer if (isGroupSummary || !mProxyByGroupTmp.containsKey(groupKey)) { 241cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer mProxyByGroupTmp.put(groupKey, record); 242cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer } 243cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer } 244cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // assign global sort key: 245cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // is_recently_intrusive:group_rank:is_group_summary:group_sort_key:rank 246cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer for (int i = 0; i < N; i++) { 247cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer final NotificationRecord record = notificationList.get(i); 248cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer NotificationRecord groupProxy = mProxyByGroupTmp.get(record.getGroupKey()); 249cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer String groupSortKey = record.getNotification().getSortKey(); 250cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer 251cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // We need to make sure the developer provided group sort key (gsk) is handled 252cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // correctly: 253cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // gsk="" < gsk=non-null-string < gsk=null 254cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // 255cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer // We enforce this by using different prefixes for these three cases. 256cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer String groupSortKeyPortion; 257cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer if (groupSortKey == null) { 258cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer groupSortKeyPortion = "nsk"; 259cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer } else if (groupSortKey.equals("")) { 260cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer groupSortKeyPortion = "esk"; 261cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer } else { 262cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer groupSortKeyPortion = "gsk=" + groupSortKey; 263cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer } 264cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer 265cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer boolean isGroupSummary = record.getNotification().isGroupSummary(); 266cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer record.setGlobalSortKey( 267cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer String.format("intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x", 268cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer record.isRecentlyIntrusive() ? '0' : '1', 269cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer groupProxy.getAuthoritativeRank(), 270cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer isGroupSummary ? '0' : '1', 271cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer groupSortKeyPortion, 272cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer record.getAuthoritativeRank())); 273cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer } 274cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer mProxyByGroupTmp.clear(); 2751031c974855ff4117a6d7866e664295786840319Chris Wren } 276cd4adf8b5ef9ac1f90fdddbb405404e173aedc87Christoph Studer 2771031c974855ff4117a6d7866e664295786840319Chris Wren // Do a second ranking pass, using group proxies 2781031c974855ff4117a6d7866e664295786840319Chris Wren Collections.sort(notificationList, mFinalComparator); 27954bbef435ed857fc68941672799fc8001c101119Chris Wren } 28054bbef435ed857fc68941672799fc8001c101119Chris Wren 28154bbef435ed857fc68941672799fc8001c101119Chris Wren public int indexOf(ArrayList<NotificationRecord> notificationList, NotificationRecord target) { 2821031c974855ff4117a6d7866e664295786840319Chris Wren return Collections.binarySearch(notificationList, target, mFinalComparator); 28354bbef435ed857fc68941672799fc8001c101119Chris Wren } 28454bbef435ed857fc68941672799fc8001c101119Chris Wren 28554bbef435ed857fc68941672799fc8001c101119Chris Wren private static int safeInt(XmlPullParser parser, String att, int defValue) { 28654bbef435ed857fc68941672799fc8001c101119Chris Wren final String val = parser.getAttributeValue(null, att); 28754bbef435ed857fc68941672799fc8001c101119Chris Wren return tryParseInt(val, defValue); 28854bbef435ed857fc68941672799fc8001c101119Chris Wren } 28954bbef435ed857fc68941672799fc8001c101119Chris Wren 29054bbef435ed857fc68941672799fc8001c101119Chris Wren private static int tryParseInt(String value, int defValue) { 29154bbef435ed857fc68941672799fc8001c101119Chris Wren if (TextUtils.isEmpty(value)) return defValue; 29254bbef435ed857fc68941672799fc8001c101119Chris Wren try { 29354bbef435ed857fc68941672799fc8001c101119Chris Wren return Integer.valueOf(value); 29454bbef435ed857fc68941672799fc8001c101119Chris Wren } catch (NumberFormatException e) { 29554bbef435ed857fc68941672799fc8001c101119Chris Wren return defValue; 29654bbef435ed857fc68941672799fc8001c101119Chris Wren } 29754bbef435ed857fc68941672799fc8001c101119Chris Wren } 29854bbef435ed857fc68941672799fc8001c101119Chris Wren 29954bbef435ed857fc68941672799fc8001c101119Chris Wren @Override 30054bbef435ed857fc68941672799fc8001c101119Chris Wren public int getPackagePriority(String packageName, int uid) { 30154bbef435ed857fc68941672799fc8001c101119Chris Wren int priority = Notification.PRIORITY_DEFAULT; 30254bbef435ed857fc68941672799fc8001c101119Chris Wren SparseIntArray priorityByUid = mPackagePriorities.get(packageName); 30354bbef435ed857fc68941672799fc8001c101119Chris Wren if (priorityByUid != null) { 30454bbef435ed857fc68941672799fc8001c101119Chris Wren priority = priorityByUid.get(uid, Notification.PRIORITY_DEFAULT); 30554bbef435ed857fc68941672799fc8001c101119Chris Wren } 30654bbef435ed857fc68941672799fc8001c101119Chris Wren return priority; 30754bbef435ed857fc68941672799fc8001c101119Chris Wren } 30854bbef435ed857fc68941672799fc8001c101119Chris Wren 30954bbef435ed857fc68941672799fc8001c101119Chris Wren @Override 31054bbef435ed857fc68941672799fc8001c101119Chris Wren public void setPackagePriority(String packageName, int uid, int priority) { 31154bbef435ed857fc68941672799fc8001c101119Chris Wren if (priority == getPackagePriority(packageName, uid)) { 31254bbef435ed857fc68941672799fc8001c101119Chris Wren return; 31354bbef435ed857fc68941672799fc8001c101119Chris Wren } 31454bbef435ed857fc68941672799fc8001c101119Chris Wren SparseIntArray priorityByUid = mPackagePriorities.get(packageName); 31554bbef435ed857fc68941672799fc8001c101119Chris Wren if (priorityByUid == null) { 31654bbef435ed857fc68941672799fc8001c101119Chris Wren priorityByUid = new SparseIntArray(); 31754bbef435ed857fc68941672799fc8001c101119Chris Wren mPackagePriorities.put(packageName, priorityByUid); 31854bbef435ed857fc68941672799fc8001c101119Chris Wren } 31954bbef435ed857fc68941672799fc8001c101119Chris Wren priorityByUid.put(uid, priority); 32054bbef435ed857fc68941672799fc8001c101119Chris Wren updateConfig(); 32154bbef435ed857fc68941672799fc8001c101119Chris Wren } 32254bbef435ed857fc68941672799fc8001c101119Chris Wren 3233ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren @Override 3243ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren public int getPackageVisibilityOverride(String packageName, int uid) { 3253ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren int visibility = NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE; 3263ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName); 3273ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (visibilityByUid != null) { 3283ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren visibility = visibilityByUid.get(uid, 3293ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE); 3303ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 3313ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren return visibility; 3323ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 3333ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren 3343ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren @Override 3353ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren public void setPackageVisibilityOverride(String packageName, int uid, int visibility) { 3363ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (visibility == getPackageVisibilityOverride(packageName, uid)) { 3373ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren return; 3383ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 3393ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName); 3403ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren if (visibilityByUid == null) { 3413ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren visibilityByUid = new SparseIntArray(); 3423ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren mPackageVisibilities.put(packageName, visibilityByUid); 3433ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 3443ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren visibilityByUid.put(uid, visibility); 3453ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren updateConfig(); 3463ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren } 3473ad4e3a45bbe44129b14c4d391431e44f1e04f0cChris Wren 34854bbef435ed857fc68941672799fc8001c101119Chris Wren public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) { 34954bbef435ed857fc68941672799fc8001c101119Chris Wren if (filter == null) { 35054bbef435ed857fc68941672799fc8001c101119Chris Wren final int N = mSignalExtractors.length; 35154bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(prefix); 35254bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print("mSignalExtractors.length = "); 35354bbef435ed857fc68941672799fc8001c101119Chris Wren pw.println(N); 35454bbef435ed857fc68941672799fc8001c101119Chris Wren for (int i = 0; i < N; i++) { 35554bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(prefix); 35654bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(" "); 35754bbef435ed857fc68941672799fc8001c101119Chris Wren pw.println(mSignalExtractors[i]); 35854bbef435ed857fc68941672799fc8001c101119Chris Wren } 35954bbef435ed857fc68941672799fc8001c101119Chris Wren } 36054bbef435ed857fc68941672799fc8001c101119Chris Wren final int N = mPackagePriorities.size(); 36154bbef435ed857fc68941672799fc8001c101119Chris Wren if (filter == null) { 36254bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(prefix); 36354bbef435ed857fc68941672799fc8001c101119Chris Wren pw.println("package priorities:"); 36454bbef435ed857fc68941672799fc8001c101119Chris Wren } 36554bbef435ed857fc68941672799fc8001c101119Chris Wren for (int i = 0; i < N; i++) { 36654bbef435ed857fc68941672799fc8001c101119Chris Wren String name = mPackagePriorities.keyAt(i); 36754bbef435ed857fc68941672799fc8001c101119Chris Wren if (filter == null || filter.matches(name)) { 36854bbef435ed857fc68941672799fc8001c101119Chris Wren SparseIntArray priorityByUid = mPackagePriorities.get(name); 36954bbef435ed857fc68941672799fc8001c101119Chris Wren final int M = priorityByUid.size(); 37054bbef435ed857fc68941672799fc8001c101119Chris Wren for (int j = 0; j < M; j++) { 37154bbef435ed857fc68941672799fc8001c101119Chris Wren int uid = priorityByUid.keyAt(j); 37254bbef435ed857fc68941672799fc8001c101119Chris Wren int priority = priorityByUid.get(uid); 37354bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(prefix); 37454bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(" "); 37554bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(name); 37654bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(" ("); 37754bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(uid); 37854bbef435ed857fc68941672799fc8001c101119Chris Wren pw.print(") has priority: "); 37954bbef435ed857fc68941672799fc8001c101119Chris Wren pw.println(priority); 38054bbef435ed857fc68941672799fc8001c101119Chris Wren } 38154bbef435ed857fc68941672799fc8001c101119Chris Wren } 38254bbef435ed857fc68941672799fc8001c101119Chris Wren } 38354bbef435ed857fc68941672799fc8001c101119Chris Wren } 38454bbef435ed857fc68941672799fc8001c101119Chris Wren} 385