Collapses ForegroundServiceControllerImpl into interface.
ForegroundServiceControllerImpl was the only implementation of ForegroundServiceController; this change eliminates the interface so that the class can be broken up into more granular components in a future CL to help break circular dependencies. No functional changes. Test: atest SystemUITests, manual Change-Id: Iabe8ae1dbc42769d5b3e93ebe2249cdc5c3e4e77
This commit is contained in:
@@ -216,12 +216,6 @@ public abstract class DependencyBinder {
|
||||
public abstract VolumeDialogController provideVolumeDialogController(
|
||||
VolumeDialogControllerImpl controllerImpl);
|
||||
|
||||
/**
|
||||
*/
|
||||
@Binds
|
||||
public abstract ForegroundServiceController provideForegroundService(
|
||||
ForegroundServiceControllerImpl controllerImpl);
|
||||
|
||||
/**
|
||||
*/
|
||||
@Binds
|
||||
|
||||
@@ -15,65 +15,322 @@
|
||||
package com.android.systemui;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
public interface ForegroundServiceController {
|
||||
/**
|
||||
* @param sbn notification that was just posted
|
||||
* @param importance
|
||||
*/
|
||||
void addNotification(StatusBarNotification sbn, int importance);
|
||||
import com.android.internal.messages.nano.SystemMessageProto;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Foreground service controller, a/k/a Dianne's Dungeon.
|
||||
*/
|
||||
@Singleton
|
||||
public class ForegroundServiceController {
|
||||
|
||||
// shelf life of foreground services before they go bad
|
||||
private static final long FG_SERVICE_GRACE_MILLIS = 5000;
|
||||
|
||||
private static final String TAG = "FgServiceController";
|
||||
private static final boolean DBG = false;
|
||||
|
||||
private final Context mContext;
|
||||
private final SparseArray<UserServices> mUserServices = new SparseArray<>();
|
||||
private final Object mMutex = new Object();
|
||||
|
||||
@Inject
|
||||
public ForegroundServiceController(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sbn notification that was just changed in some way
|
||||
* @param newImportance
|
||||
*/
|
||||
void updateNotification(StatusBarNotification sbn, int newImportance);
|
||||
|
||||
/**
|
||||
* @param sbn notification that was just canceled
|
||||
*/
|
||||
boolean removeNotification(StatusBarNotification sbn);
|
||||
|
||||
/**
|
||||
* @param userId
|
||||
* @return true if this user has services missing notifications and therefore needs a
|
||||
* disclosure notification.
|
||||
*/
|
||||
boolean isDungeonNeededForUser(int userId);
|
||||
|
||||
/**
|
||||
* @param sbn
|
||||
* @return true if sbn is the system-provided "dungeon" (list of running foreground services).
|
||||
*/
|
||||
boolean isDungeonNotification(StatusBarNotification sbn);
|
||||
|
||||
/**
|
||||
* @return true if sbn is one of the window manager "drawing over other apps" notifications
|
||||
*/
|
||||
boolean isSystemAlertNotification(StatusBarNotification sbn);
|
||||
|
||||
/**
|
||||
* Returns the key of the foreground service from this package using the standard template,
|
||||
* if one exists.
|
||||
*/
|
||||
@Nullable String getStandardLayoutKey(int userId, String pkg);
|
||||
public boolean isDungeonNeededForUser(int userId) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices services = mUserServices.get(userId);
|
||||
if (services == null) return false;
|
||||
return services.isDungeonNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this user/pkg has a missing or custom layout notification and therefore needs
|
||||
* a disclosure notification for system alert windows.
|
||||
*/
|
||||
boolean isSystemAlertWarningNeeded(int userId, String pkg);
|
||||
public boolean isSystemAlertWarningNeeded(int userId, String pkg) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices services = mUserServices.get(userId);
|
||||
if (services == null) return false;
|
||||
return services.getStandardLayoutKey(pkg) == null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key of the foreground service from this package using the standard template,
|
||||
* if one exists.
|
||||
*/
|
||||
@Nullable
|
||||
public String getStandardLayoutKey(int userId, String pkg) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices services = mUserServices.get(userId);
|
||||
if (services == null) return null;
|
||||
return services.getStandardLayoutKey(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets active app ops for this user and package
|
||||
*/
|
||||
@Nullable
|
||||
public ArraySet<Integer> getAppOps(int userId, String pkg) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices services = mUserServices.get(userId);
|
||||
if (services == null) {
|
||||
return null;
|
||||
}
|
||||
return services.getFeatures(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Records active app ops. App Ops are stored in FSC in addition to NotificationData in
|
||||
* case they change before we have a notification to tag.
|
||||
*/
|
||||
void onAppOpChanged(int code, int uid, String packageName, boolean active);
|
||||
public void onAppOpChanged(int code, int uid, String packageName, boolean active) {
|
||||
int userId = UserHandle.getUserId(uid);
|
||||
synchronized (mMutex) {
|
||||
UserServices userServices = mUserServices.get(userId);
|
||||
if (userServices == null) {
|
||||
userServices = new UserServices();
|
||||
mUserServices.put(userId, userServices);
|
||||
}
|
||||
if (active) {
|
||||
userServices.addOp(packageName, code);
|
||||
} else {
|
||||
userServices.removeOp(packageName, code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets active app ops for this user and package
|
||||
* @param sbn notification that was just posted
|
||||
* @param importance
|
||||
*/
|
||||
@Nullable ArraySet<Integer> getAppOps(int userId, String packageName);
|
||||
public void addNotification(StatusBarNotification sbn, int importance) {
|
||||
updateNotification(sbn, importance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sbn notification that was just removed
|
||||
*/
|
||||
public boolean removeNotification(StatusBarNotification sbn) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices userServices = mUserServices.get(sbn.getUserId());
|
||||
if (userServices == null) {
|
||||
if (DBG) {
|
||||
Log.w(TAG, String.format(
|
||||
"user %d with no known notifications got removeNotification for %s",
|
||||
sbn.getUserId(), sbn));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (isDungeonNotification(sbn)) {
|
||||
// if you remove the dungeon entirely, we take that to mean there are
|
||||
// no running services
|
||||
userServices.setRunningServices(null, 0);
|
||||
return true;
|
||||
} else {
|
||||
// this is safe to call on any notification, not just FLAG_FOREGROUND_SERVICE
|
||||
return userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sbn notification that was just changed in some way
|
||||
*/
|
||||
public void updateNotification(StatusBarNotification sbn, int newImportance) {
|
||||
synchronized (mMutex) {
|
||||
UserServices userServices = mUserServices.get(sbn.getUserId());
|
||||
if (userServices == null) {
|
||||
userServices = new UserServices();
|
||||
mUserServices.put(sbn.getUserId(), userServices);
|
||||
}
|
||||
|
||||
if (isDungeonNotification(sbn)) {
|
||||
final Bundle extras = sbn.getNotification().extras;
|
||||
if (extras != null) {
|
||||
final String[] svcs = extras.getStringArray(Notification.EXTRA_FOREGROUND_APPS);
|
||||
userServices.setRunningServices(svcs, sbn.getNotification().when);
|
||||
}
|
||||
} else {
|
||||
userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
|
||||
if (0 != (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)) {
|
||||
if (newImportance > NotificationManager.IMPORTANCE_MIN) {
|
||||
userServices.addImportantNotification(sbn.getPackageName(), sbn.getKey());
|
||||
}
|
||||
final Notification.Builder builder = Notification.Builder.recoverBuilder(
|
||||
mContext, sbn.getNotification());
|
||||
if (builder.usesStandardHeader()) {
|
||||
userServices.addStandardLayoutNotification(
|
||||
sbn.getPackageName(), sbn.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if sbn is the system-provided "dungeon" (list of running foreground services).
|
||||
*/
|
||||
public boolean isDungeonNotification(StatusBarNotification sbn) {
|
||||
return sbn.getId() == SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES
|
||||
&& sbn.getTag() == null
|
||||
&& sbn.getPackageName().equals("android");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if sbn is one of the window manager "drawing over other apps" notifications
|
||||
*/
|
||||
public boolean isSystemAlertNotification(StatusBarNotification sbn) {
|
||||
return sbn.getPackageName().equals("android")
|
||||
&& sbn.getTag() != null
|
||||
&& sbn.getTag().contains("AlertWindowNotification");
|
||||
}
|
||||
|
||||
/**
|
||||
* Struct to track relevant packages and notifications for a userid's foreground services.
|
||||
*/
|
||||
private static class UserServices {
|
||||
private String[] mRunning = null;
|
||||
private long mServiceStartTime = 0;
|
||||
// package -> sufficiently important posted notification keys
|
||||
private ArrayMap<String, ArraySet<String>> mImportantNotifications = new ArrayMap<>(1);
|
||||
// package -> standard layout posted notification keys
|
||||
private ArrayMap<String, ArraySet<String>> mStandardLayoutNotifications = new ArrayMap<>(1);
|
||||
|
||||
// package -> app ops
|
||||
private ArrayMap<String, ArraySet<Integer>> mAppOps = new ArrayMap<>(1);
|
||||
|
||||
public void setRunningServices(String[] pkgs, long serviceStartTime) {
|
||||
mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null;
|
||||
mServiceStartTime = serviceStartTime;
|
||||
}
|
||||
|
||||
public void addOp(String pkg, int op) {
|
||||
if (mAppOps.get(pkg) == null) {
|
||||
mAppOps.put(pkg, new ArraySet<>(3));
|
||||
}
|
||||
mAppOps.get(pkg).add(op);
|
||||
}
|
||||
|
||||
public boolean removeOp(String pkg, int op) {
|
||||
final boolean found;
|
||||
final ArraySet<Integer> keys = mAppOps.get(pkg);
|
||||
if (keys == null) {
|
||||
found = false;
|
||||
} else {
|
||||
found = keys.remove(op);
|
||||
if (keys.size() == 0) {
|
||||
mAppOps.remove(pkg);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public void addImportantNotification(String pkg, String key) {
|
||||
addNotification(mImportantNotifications, pkg, key);
|
||||
}
|
||||
|
||||
public boolean removeImportantNotification(String pkg, String key) {
|
||||
return removeNotification(mImportantNotifications, pkg, key);
|
||||
}
|
||||
|
||||
public void addStandardLayoutNotification(String pkg, String key) {
|
||||
addNotification(mStandardLayoutNotifications, pkg, key);
|
||||
}
|
||||
|
||||
public boolean removeStandardLayoutNotification(String pkg, String key) {
|
||||
return removeNotification(mStandardLayoutNotifications, pkg, key);
|
||||
}
|
||||
|
||||
public boolean removeNotification(String pkg, String key) {
|
||||
boolean removed = false;
|
||||
removed |= removeImportantNotification(pkg, key);
|
||||
removed |= removeStandardLayoutNotification(pkg, key);
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void addNotification(ArrayMap<String, ArraySet<String>> map, String pkg,
|
||||
String key) {
|
||||
if (map.get(pkg) == null) {
|
||||
map.put(pkg, new ArraySet<>());
|
||||
}
|
||||
map.get(pkg).add(key);
|
||||
}
|
||||
|
||||
public boolean removeNotification(ArrayMap<String, ArraySet<String>> map,
|
||||
String pkg, String key) {
|
||||
final boolean found;
|
||||
final ArraySet<String> keys = map.get(pkg);
|
||||
if (keys == null) {
|
||||
found = false;
|
||||
} else {
|
||||
found = keys.remove(key);
|
||||
if (keys.size() == 0) {
|
||||
map.remove(pkg);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public boolean isDungeonNeeded() {
|
||||
if (mRunning != null
|
||||
&& System.currentTimeMillis() - mServiceStartTime >= FG_SERVICE_GRACE_MILLIS) {
|
||||
|
||||
for (String pkg : mRunning) {
|
||||
final ArraySet<String> set = mImportantNotifications.get(pkg);
|
||||
if (set == null || set.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ArraySet<Integer> getFeatures(String pkg) {
|
||||
return mAppOps.get(pkg);
|
||||
}
|
||||
|
||||
public String getStandardLayoutKey(String pkg) {
|
||||
final ArraySet<String> set = mStandardLayoutNotifications.get(pkg);
|
||||
if (set == null || set.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return set.valueAt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserServices{"
|
||||
+ "mRunning=" + Arrays.toString(mRunning)
|
||||
+ ", mServiceStartTime=" + mServiceStartTime
|
||||
+ ", mImportantNotifications=" + mImportantNotifications
|
||||
+ ", mStandardLayoutNotifications=" + mStandardLayoutNotifications
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the
|
||||
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.messages.nano.SystemMessageProto;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Foreground service controller, a/k/a Dianne's Dungeon.
|
||||
*/
|
||||
@Singleton
|
||||
public class ForegroundServiceControllerImpl
|
||||
implements ForegroundServiceController {
|
||||
|
||||
// shelf life of foreground services before they go bad
|
||||
public static final long FG_SERVICE_GRACE_MILLIS = 5000;
|
||||
|
||||
private static final String TAG = "FgServiceController";
|
||||
private static final boolean DBG = false;
|
||||
|
||||
private final Context mContext;
|
||||
private final SparseArray<UserServices> mUserServices = new SparseArray<>();
|
||||
private final Object mMutex = new Object();
|
||||
|
||||
@Inject
|
||||
public ForegroundServiceControllerImpl(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDungeonNeededForUser(int userId) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices services = mUserServices.get(userId);
|
||||
if (services == null) return false;
|
||||
return services.isDungeonNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSystemAlertWarningNeeded(int userId, String pkg) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices services = mUserServices.get(userId);
|
||||
if (services == null) return false;
|
||||
return services.getStandardLayoutKey(pkg) == null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStandardLayoutKey(int userId, String pkg) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices services = mUserServices.get(userId);
|
||||
if (services == null) return null;
|
||||
return services.getStandardLayoutKey(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArraySet<Integer> getAppOps(int userId, String pkg) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices services = mUserServices.get(userId);
|
||||
if (services == null) {
|
||||
return null;
|
||||
}
|
||||
return services.getFeatures(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppOpChanged(int code, int uid, String packageName, boolean active) {
|
||||
int userId = UserHandle.getUserId(uid);
|
||||
synchronized (mMutex) {
|
||||
UserServices userServices = mUserServices.get(userId);
|
||||
if (userServices == null) {
|
||||
userServices = new UserServices();
|
||||
mUserServices.put(userId, userServices);
|
||||
}
|
||||
if (active) {
|
||||
userServices.addOp(packageName, code);
|
||||
} else {
|
||||
userServices.removeOp(packageName, code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotification(StatusBarNotification sbn, int importance) {
|
||||
updateNotification(sbn, importance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeNotification(StatusBarNotification sbn) {
|
||||
synchronized (mMutex) {
|
||||
final UserServices userServices = mUserServices.get(sbn.getUserId());
|
||||
if (userServices == null) {
|
||||
if (DBG) {
|
||||
Log.w(TAG, String.format(
|
||||
"user %d with no known notifications got removeNotification for %s",
|
||||
sbn.getUserId(), sbn));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (isDungeonNotification(sbn)) {
|
||||
// if you remove the dungeon entirely, we take that to mean there are
|
||||
// no running services
|
||||
userServices.setRunningServices(null, 0);
|
||||
return true;
|
||||
} else {
|
||||
// this is safe to call on any notification, not just FLAG_FOREGROUND_SERVICE
|
||||
return userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNotification(StatusBarNotification sbn, int newImportance) {
|
||||
synchronized (mMutex) {
|
||||
UserServices userServices = mUserServices.get(sbn.getUserId());
|
||||
if (userServices == null) {
|
||||
userServices = new UserServices();
|
||||
mUserServices.put(sbn.getUserId(), userServices);
|
||||
}
|
||||
|
||||
if (isDungeonNotification(sbn)) {
|
||||
final Bundle extras = sbn.getNotification().extras;
|
||||
if (extras != null) {
|
||||
final String[] svcs = extras.getStringArray(Notification.EXTRA_FOREGROUND_APPS);
|
||||
userServices.setRunningServices(svcs, sbn.getNotification().when);
|
||||
}
|
||||
} else {
|
||||
userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
|
||||
if (0 != (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)) {
|
||||
if (newImportance > NotificationManager.IMPORTANCE_MIN) {
|
||||
userServices.addImportantNotification(sbn.getPackageName(), sbn.getKey());
|
||||
}
|
||||
final Notification.Builder builder = Notification.Builder.recoverBuilder(
|
||||
mContext, sbn.getNotification());
|
||||
if (builder.usesStandardHeader()) {
|
||||
userServices.addStandardLayoutNotification(
|
||||
sbn.getPackageName(), sbn.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDungeonNotification(StatusBarNotification sbn) {
|
||||
return sbn.getId() == SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES
|
||||
&& sbn.getTag() == null
|
||||
&& sbn.getPackageName().equals("android");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSystemAlertNotification(StatusBarNotification sbn) {
|
||||
return sbn.getPackageName().equals("android")
|
||||
&& sbn.getTag() != null
|
||||
&& sbn.getTag().contains("AlertWindowNotification");
|
||||
}
|
||||
|
||||
/**
|
||||
* Struct to track relevant packages and notifications for a userid's foreground services.
|
||||
*/
|
||||
private static class UserServices {
|
||||
private String[] mRunning = null;
|
||||
private long mServiceStartTime = 0;
|
||||
// package -> sufficiently important posted notification keys
|
||||
private ArrayMap<String, ArraySet<String>> mImportantNotifications = new ArrayMap<>(1);
|
||||
// package -> standard layout posted notification keys
|
||||
private ArrayMap<String, ArraySet<String>> mStandardLayoutNotifications = new ArrayMap<>(1);
|
||||
|
||||
// package -> app ops
|
||||
private ArrayMap<String, ArraySet<Integer>> mAppOps = new ArrayMap<>(1);
|
||||
|
||||
public void setRunningServices(String[] pkgs, long serviceStartTime) {
|
||||
mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null;
|
||||
mServiceStartTime = serviceStartTime;
|
||||
}
|
||||
|
||||
public void addOp(String pkg, int op) {
|
||||
if (mAppOps.get(pkg) == null) {
|
||||
mAppOps.put(pkg, new ArraySet<>(3));
|
||||
}
|
||||
mAppOps.get(pkg).add(op);
|
||||
}
|
||||
|
||||
public boolean removeOp(String pkg, int op) {
|
||||
final boolean found;
|
||||
final ArraySet<Integer> keys = mAppOps.get(pkg);
|
||||
if (keys == null) {
|
||||
found = false;
|
||||
} else {
|
||||
found = keys.remove(op);
|
||||
if (keys.size() == 0) {
|
||||
mAppOps.remove(pkg);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public void addImportantNotification(String pkg, String key) {
|
||||
addNotification(mImportantNotifications, pkg, key);
|
||||
}
|
||||
|
||||
public boolean removeImportantNotification(String pkg, String key) {
|
||||
return removeNotification(mImportantNotifications, pkg, key);
|
||||
}
|
||||
|
||||
public void addStandardLayoutNotification(String pkg, String key) {
|
||||
addNotification(mStandardLayoutNotifications, pkg, key);
|
||||
}
|
||||
|
||||
public boolean removeStandardLayoutNotification(String pkg, String key) {
|
||||
return removeNotification(mStandardLayoutNotifications, pkg, key);
|
||||
}
|
||||
|
||||
public boolean removeNotification(String pkg, String key) {
|
||||
boolean removed = false;
|
||||
removed |= removeImportantNotification(pkg, key);
|
||||
removed |= removeStandardLayoutNotification(pkg, key);
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void addNotification(ArrayMap<String, ArraySet<String>> map, String pkg,
|
||||
String key) {
|
||||
if (map.get(pkg) == null) {
|
||||
map.put(pkg, new ArraySet<>());
|
||||
}
|
||||
map.get(pkg).add(key);
|
||||
}
|
||||
|
||||
public boolean removeNotification(ArrayMap<String, ArraySet<String>> map,
|
||||
String pkg, String key) {
|
||||
final boolean found;
|
||||
final ArraySet<String> keys = map.get(pkg);
|
||||
if (keys == null) {
|
||||
found = false;
|
||||
} else {
|
||||
found = keys.remove(key);
|
||||
if (keys.size() == 0) {
|
||||
map.remove(pkg);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public boolean isDungeonNeeded() {
|
||||
if (mRunning != null
|
||||
&& System.currentTimeMillis() - mServiceStartTime >= FG_SERVICE_GRACE_MILLIS) {
|
||||
|
||||
for (String pkg : mRunning) {
|
||||
final ArraySet<String> set = mImportantNotifications.get(pkg);
|
||||
if (set == null || set.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ArraySet<Integer> getFeatures(String pkg) {
|
||||
return mAppOps.get(pkg);
|
||||
}
|
||||
|
||||
public String getStandardLayoutKey(String pkg) {
|
||||
final ArraySet<String> set = mStandardLayoutNotifications.get(pkg);
|
||||
if (set == null || set.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return set.valueAt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserServices{" +
|
||||
"mRunning=" + Arrays.toString(mRunning) +
|
||||
", mServiceStartTime=" + mServiceStartTime +
|
||||
", mImportantNotifications=" + mImportantNotifications +
|
||||
", mStandardLayoutNotifications=" + mStandardLayoutNotifications +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
fsc = new ForegroundServiceControllerImpl(mContext);
|
||||
fsc = new ForegroundServiceController(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user