1 /* 2 * Copyright (C) 2018 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 17 package com.android.systemui; 18 19 import android.util.ArrayMap; 20 import android.util.ArraySet; 21 22 import java.util.Arrays; 23 24 /** 25 * Struct to track relevant packages and notifications for a userid's foreground services. 26 */ 27 class ForegroundServicesUserState { 28 // shelf life of foreground services before they go bad 29 private static final long FG_SERVICE_GRACE_MILLIS = 5000; 30 31 private String[] mRunning = null; 32 private long mServiceStartTime = 0; 33 // package -> sufficiently important posted notification keys 34 private ArrayMap<String, ArraySet<String>> mImportantNotifications = new ArrayMap<>(1); 35 // package -> standard layout posted notification keys 36 private ArrayMap<String, ArraySet<String>> mStandardLayoutNotifications = new ArrayMap<>(1); 37 38 // package -> app ops 39 private ArrayMap<String, ArraySet<Integer>> mAppOps = new ArrayMap<>(1); 40 setRunningServices(String[] pkgs, long serviceStartTime)41 public void setRunningServices(String[] pkgs, long serviceStartTime) { 42 mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null; 43 mServiceStartTime = serviceStartTime; 44 } 45 addOp(String pkg, int op)46 public void addOp(String pkg, int op) { 47 if (mAppOps.get(pkg) == null) { 48 mAppOps.put(pkg, new ArraySet<>(3)); 49 } 50 mAppOps.get(pkg).add(op); 51 } 52 removeOp(String pkg, int op)53 public boolean removeOp(String pkg, int op) { 54 final boolean found; 55 final ArraySet<Integer> keys = mAppOps.get(pkg); 56 if (keys == null) { 57 found = false; 58 } else { 59 found = keys.remove(op); 60 if (keys.size() == 0) { 61 mAppOps.remove(pkg); 62 } 63 } 64 return found; 65 } 66 addImportantNotification(String pkg, String key)67 public void addImportantNotification(String pkg, String key) { 68 addNotification(mImportantNotifications, pkg, key); 69 } 70 removeImportantNotification(String pkg, String key)71 public boolean removeImportantNotification(String pkg, String key) { 72 return removeNotification(mImportantNotifications, pkg, key); 73 } 74 addStandardLayoutNotification(String pkg, String key)75 public void addStandardLayoutNotification(String pkg, String key) { 76 addNotification(mStandardLayoutNotifications, pkg, key); 77 } 78 removeStandardLayoutNotification(String pkg, String key)79 public boolean removeStandardLayoutNotification(String pkg, String key) { 80 return removeNotification(mStandardLayoutNotifications, pkg, key); 81 } 82 removeNotification(String pkg, String key)83 public boolean removeNotification(String pkg, String key) { 84 boolean removed = false; 85 removed |= removeImportantNotification(pkg, key); 86 removed |= removeStandardLayoutNotification(pkg, key); 87 return removed; 88 } 89 addNotification(ArrayMap<String, ArraySet<String>> map, String pkg, String key)90 public void addNotification(ArrayMap<String, ArraySet<String>> map, String pkg, 91 String key) { 92 if (map.get(pkg) == null) { 93 map.put(pkg, new ArraySet<>()); 94 } 95 map.get(pkg).add(key); 96 } 97 removeNotification(ArrayMap<String, ArraySet<String>> map, String pkg, String key)98 public boolean removeNotification(ArrayMap<String, ArraySet<String>> map, 99 String pkg, String key) { 100 final boolean found; 101 final ArraySet<String> keys = map.get(pkg); 102 if (keys == null) { 103 found = false; 104 } else { 105 found = keys.remove(key); 106 if (keys.size() == 0) { 107 map.remove(pkg); 108 } 109 } 110 return found; 111 } 112 isDisclosureNeeded()113 public boolean isDisclosureNeeded() { 114 if (mRunning != null 115 && System.currentTimeMillis() - mServiceStartTime 116 >= FG_SERVICE_GRACE_MILLIS) { 117 118 for (String pkg : mRunning) { 119 final ArraySet<String> set = mImportantNotifications.get(pkg); 120 if (set == null || set.size() == 0) { 121 return true; 122 } 123 } 124 } 125 return false; 126 } 127 getFeatures(String pkg)128 public ArraySet<Integer> getFeatures(String pkg) { 129 return mAppOps.get(pkg); 130 } 131 getStandardLayoutKey(String pkg)132 public String getStandardLayoutKey(String pkg) { 133 final ArraySet<String> set = mStandardLayoutNotifications.get(pkg); 134 if (set == null || set.size() == 0) { 135 return null; 136 } 137 return set.valueAt(0); 138 } 139 140 @Override toString()141 public String toString() { 142 return "UserServices{" 143 + "mRunning=" + Arrays.toString(mRunning) 144 + ", mServiceStartTime=" + mServiceStartTime 145 + ", mImportantNotifications=" + mImportantNotifications 146 + ", mStandardLayoutNotifications=" + mStandardLayoutNotifications 147 + '}'; 148 } 149 } 150