Merge "No notification actions" into rvc-dev am: cfcf1be595 am: 78d7118848

Change-Id: I9557e5b06b34e0d8b2086f4677b67247af2d174a
This commit is contained in:
Jay Aliomer
2020-04-15 23:29:50 +00:00
committed by Automerger Merge Worker
6 changed files with 239 additions and 97 deletions

View File

@@ -30,6 +30,7 @@ import android.provider.Settings;
import android.service.notification.Condition;
import android.service.notification.ConditionProviderService;
import android.service.notification.IConditionProvider;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -54,7 +55,6 @@ public class ConditionProviders extends ManagedServices {
private final ArraySet<String> mSystemConditionProviderNames;
private final ArraySet<SystemConditionProviderService> mSystemConditionProviders
= new ArraySet<>();
private Callback mCallback;
public ConditionProviders(Context context, UserProfiles userProfiles, IPackageManager pm) {
@@ -194,6 +194,21 @@ public class ConditionProviders extends ManagedServices {
}
}
@Override
protected void loadDefaultsFromConfig() {
String defaultDndAccess = mContext.getResources().getString(
R.string.config_defaultDndAccessPackages);
if (defaultDndAccess != null) {
String[] dnds = defaultDndAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
for (int i = 0; i < dnds.length; i++) {
if (TextUtils.isEmpty(dnds[i])) {
continue;
}
addDefaultComponentOrPackage(dnds[i]);
}
}
}
@Override
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
if (removed == null) return;

View File

@@ -21,6 +21,7 @@ import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_FOREGROUND_SERVICE;
import static android.content.Context.DEVICE_POLICY_SERVICE;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_SYSTEM;
import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -96,6 +97,8 @@ abstract public class ManagedServices {
private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
protected static final String ENABLED_SERVICES_SEPARATOR = ":";
private static final String DB_VERSION_1 = "1";
/**
* List of components and apps that can have running {@link ManagedServices}.
@@ -107,7 +110,7 @@ abstract public class ManagedServices {
static final String ATT_VERSION = "version";
static final String ATT_DEFAULTS = "defaults";
static final int DB_VERSION = 1;
static final int DB_VERSION = 2;
static final int APPROVAL_BY_PACKAGE = 0;
static final int APPROVAL_BY_COMPONENT = 1;
@@ -187,17 +190,22 @@ abstract public class ManagedServices {
protected void addDefaultComponentOrPackage(String packageOrComponent) {
if (!TextUtils.isEmpty(packageOrComponent)) {
synchronized (mDefaultsLock) {
ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
if (cn == null) {
if (mApprovalLevel == APPROVAL_BY_PACKAGE) {
mDefaultPackages.add(packageOrComponent);
} else {
return;
}
ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
if (cn != null && mApprovalLevel == APPROVAL_BY_COMPONENT) {
mDefaultPackages.add(cn.getPackageName());
mDefaultComponents.add(cn);
return;
}
}
}
}
protected abstract void loadDefaultsFromConfig();
boolean isDefaultComponentOrPackage(String packageOrComponent) {
synchronized (mDefaultsLock) {
ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
@@ -504,19 +512,19 @@ abstract public class ManagedServices {
void readDefaults(XmlPullParser parser) {
String defaultComponents = XmlUtils.readStringAttribute(parser, ATT_DEFAULTS);
if (defaultComponents == null) {
return;
}
String[] components = defaultComponents.split(ENABLED_SERVICES_SEPARATOR);
synchronized (mDefaultsLock) {
for (int i = 0; i < components.length; i++) {
if (!TextUtils.isEmpty(components[i])) {
ComponentName cn = ComponentName.unflattenFromString(components[i]);
if (cn != null) {
mDefaultPackages.add(cn.getPackageName());
mDefaultComponents.add(cn);
} else {
mDefaultPackages.add(components[i]);
if (!TextUtils.isEmpty(defaultComponents)) {
String[] components = defaultComponents.split(ENABLED_SERVICES_SEPARATOR);
synchronized (mDefaultsLock) {
for (int i = 0; i < components.length; i++) {
if (!TextUtils.isEmpty(components[i])) {
ComponentName cn = ComponentName.unflattenFromString(components[i]);
if (cn != null) {
mDefaultPackages.add(cn.getPackageName());
mDefaultComponents.add(cn);
} else {
mDefaultPackages.add(components[i]);
}
}
}
}
@@ -531,9 +539,11 @@ abstract public class ManagedServices {
throws XmlPullParserException, IOException {
// read grants
int type;
String version = "";
readDefaults(parser);
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
String tag = parser.getName();
version = XmlUtils.readStringAttribute(parser, ATT_VERSION);
if (type == XmlPullParser.END_TAG
&& getConfig().xmlTag.equals(tag)) {
break;
@@ -561,9 +571,38 @@ abstract public class ManagedServices {
}
}
}
boolean isVersionOne = TextUtils.isEmpty(version) || DB_VERSION_1.equals(version);
if (isVersionOne) {
upgradeToVersionTwo();
}
rebindServices(false, USER_ALL);
}
private void upgradeToVersionTwo() {
// check if any defaults are loaded
int defaultsSize = mDefaultComponents.size() + mDefaultPackages.size();
if (defaultsSize == 0) {
// load defaults from current allowed
if (this.mApprovalLevel == APPROVAL_BY_COMPONENT) {
List<ComponentName> approvedComponents = getAllowedComponents(USER_SYSTEM);
for (int i = 0; i < approvedComponents.size(); i++) {
addDefaultComponentOrPackage(approvedComponents.get(i).flattenToString());
}
}
if (this.mApprovalLevel == APPROVAL_BY_PACKAGE) {
List<String> approvedPkgs = getAllowedPackages(USER_SYSTEM);
for (int i = 0; i < approvedPkgs.size(); i++) {
addDefaultComponentOrPackage(approvedPkgs.get(i));
}
}
}
// if no defaults are loaded, then load from config
defaultsSize = mDefaultComponents.size() + mDefaultPackages.size();
if (defaultsSize == 0) {
loadDefaultsFromConfig();
}
}
/**
* Read extra attributes in the {@link #TAG_MANAGED_SERVICES} tag.
*/

View File

@@ -600,57 +600,11 @@ public class NotificationManagerService extends SystemService {
}
void loadDefaultApprovedServices(int userId) {
String defaultListenerAccess = getContext().getResources().getString(
com.android.internal.R.string.config_defaultListenerAccessPackages);
if (defaultListenerAccess != null) {
String[] listeners =
defaultListenerAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
for (int i = 0; i < listeners.length; i++) {
if (TextUtils.isEmpty(listeners[i])) {
continue;
}
ArraySet<ComponentName> approvedListeners =
mListeners.queryPackageForServices(listeners[i],
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE, userId);
for (int k = 0; k < approvedListeners.size(); k++) {
ComponentName cn = approvedListeners.valueAt(k);
mListeners.addDefaultComponentOrPackage(cn.flattenToString());
}
}
}
mListeners.loadDefaultsFromConfig();
String defaultDndAccess = getContext().getResources().getString(
com.android.internal.R.string.config_defaultDndAccessPackages);
if (defaultDndAccess != null) {
String[] dnds = defaultDndAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
for (int i = 0; i < dnds.length; i++) {
if (TextUtils.isEmpty(dnds[i])) {
continue;
}
mConditionProviders.addDefaultComponentOrPackage(dnds[i]);
}
}
mConditionProviders.loadDefaultsFromConfig();
ArraySet<String> assistants = new ArraySet<>();
String deviceAssistant = DeviceConfig.getProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE);
if (deviceAssistant != null) {
assistants.addAll(Arrays.asList(deviceAssistant.split(
ManagedServices.ENABLED_SERVICES_SEPARATOR)));
}
assistants.addAll(Arrays.asList(getContext().getResources().getString(
com.android.internal.R.string.config_defaultAssistantAccessComponent)
.split(ManagedServices.ENABLED_SERVICES_SEPARATOR)));
for (int i = 0; i < assistants.size(); i++) {
String cnString = assistants.valueAt(i);
if (TextUtils.isEmpty(cnString)) {
continue;
}
mAssistants.addDefaultComponentOrPackage(cnString);
}
mAssistants.loadDefaultsFromConfig();
}
protected void allowDefaultApprovedServices(int userId) {
@@ -673,11 +627,14 @@ public class NotificationManagerService extends SystemService {
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE);
if (overrideDefaultAssistantString != null) {
ComponentName overrideDefaultAssistant =
ComponentName.unflattenFromString(overrideDefaultAssistantString);
if (allowAssistant(userId, overrideDefaultAssistant)) return;
ArraySet<ComponentName> approved = mAssistants.queryPackageForServices(
overrideDefaultAssistantString,
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
userId);
for (int i = 0; i < approved.size(); i++) {
if (allowAssistant(userId, approved.valueAt(i))) return;
}
}
ArraySet<ComponentName> defaults = mAssistants.getDefaultComponents();
// We should have only one default assistant by default
// allowAssistant should execute once in practice
@@ -8603,6 +8560,26 @@ public class NotificationManagerService extends SystemService {
private ArrayMap<Integer, Boolean> mUserSetMap = new ArrayMap<>();
private Set<String> mAllowedAdjustments = new ArraySet<>();
@Override
protected void loadDefaultsFromConfig() {
ArraySet<String> assistants = new ArraySet<>();
assistants.addAll(Arrays.asList(mContext.getResources().getString(
com.android.internal.R.string.config_defaultAssistantAccessComponent)
.split(ManagedServices.ENABLED_SERVICES_SEPARATOR)));
for (int i = 0; i < assistants.size(); i++) {
String cnString = assistants.valueAt(i);
if (TextUtils.isEmpty(cnString)) {
continue;
}
ArraySet<ComponentName> approved = queryPackageForServices(cnString,
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, USER_SYSTEM);
for (int k = 0; k < approved.size(); k++) {
ComponentName cn = approved.valueAt(k);
addDefaultComponentOrPackage(cn.flattenToString());
}
}
}
public NotificationAssistants(Context context, Object lock, UserProfiles up,
IPackageManager pm) {
super(context, lock, up, pm);
@@ -9040,7 +9017,29 @@ public class NotificationManagerService extends SystemService {
public NotificationListeners(IPackageManager pm) {
super(getContext(), mNotificationLock, mUserProfiles, pm);
}
@Override
protected void loadDefaultsFromConfig() {
String defaultListenerAccess = mContext.getResources().getString(
R.string.config_defaultListenerAccessPackages);
if (defaultListenerAccess != null) {
String[] listeners =
defaultListenerAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
for (int i = 0; i < listeners.length; i++) {
if (TextUtils.isEmpty(listeners[i])) {
continue;
}
ArraySet<ComponentName> approvedListeners =
this.queryPackageForServices(listeners[i],
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE, USER_SYSTEM);
for (int k = 0; k < approvedListeners.size(); k++) {
ComponentName cn = approvedListeners.valueAt(k);
addDefaultComponentOrPackage(cn.flattenToString());
}
}
}
}
@Override

View File

@@ -77,6 +77,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -96,6 +97,10 @@ public class ManagedServicesTest extends UiServiceTestCase {
UserInfo mZero = new UserInfo(0, "zero", 0);
UserInfo mTen = new UserInfo(10, "ten", 0);
private String mDefaultsString;
private String mVersionString;
private final Set<ComponentName> mDefaults = new ArraySet();
private ManagedServices mService;
private static final String SETTING = "setting";
private static final String SECONDARY_SETTING = "secondary_setting";
@@ -106,8 +111,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
private ArrayMap<Integer, String> mExpectedSecondaryComponentNames;
// type : user : list of approved
private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedPrimary = new ArrayMap<>();
private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedSecondary = new ArrayMap<>();
private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedPrimary;
private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedSecondary;
@Before
public void setUp() throws Exception {
@@ -132,6 +137,9 @@ public class ManagedServicesTest extends UiServiceTestCase {
profileIds.add(12);
when(mUserProfiles.getCurrentProfileIds()).thenReturn(profileIds);
mVersionString = "2";
mExpectedPrimary = new ArrayMap<>();
mExpectedSecondary = new ArrayMap<>();
mExpectedPrimaryPackages = new ArrayMap<>();
mExpectedPrimaryPackages.put(0, "this.is.a.package.name:another.package");
mExpectedPrimaryPackages.put(10, "this.is.another.package");
@@ -155,6 +163,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
"this.is.another.package:component:package");
mExpectedSecondary.put(APPROVAL_BY_PACKAGE, mExpectedSecondaryPackages);
mExpectedSecondary.put(APPROVAL_BY_COMPONENT, mExpectedSecondaryComponentNames);
mService = new TestManagedServices(getContext(), mLock, mUserProfiles,
mIpm, APPROVAL_BY_COMPONENT);
}
@Test
@@ -1178,9 +1188,99 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
}
@Test
public void loadDefaults_noVersionNoDefaults() throws Exception {
resetComponentsAndPackages();
loadXml(mService);
assertEquals(mService.getDefaultComponents().size(), 0);
}
@Test
public void loadDefaults_noVersionNoDefaultsOneActive() throws Exception {
resetComponentsAndPackages();
mService.addDefaultComponentOrPackage("package/class");
loadXml(mService);
assertEquals(1, mService.getDefaultComponents().size());
assertTrue(mService.getDefaultComponents()
.contains(ComponentName.unflattenFromString("package/class")));
}
@Test
public void loadDefaults_noVersionWithDefaults() throws Exception {
resetComponentsAndPackages();
mDefaults.add(new ComponentName("default", "class"));
loadXml(mService);
assertEquals(mService.getDefaultComponents(), mDefaults);
}
@Test
public void loadDefaults_versionOneWithDefaultsWithActive() throws Exception {
resetComponentsAndPackages();
mDefaults.add(new ComponentName("default", "class"));
mExpectedPrimaryComponentNames.put(0, "package/class");
mVersionString = "1";
loadXml(mService);
assertEquals(mService.getDefaultComponents(),
new ArraySet(Arrays.asList(new ComponentName("package", "class"))));
}
@Test
public void loadDefaults_versionTwoWithDefaultsWithActive() throws Exception {
resetComponentsAndPackages();
mDefaults.add(new ComponentName("default", "class"));
mDefaultsString = "default/class";
mExpectedPrimaryComponentNames.put(0, "package/class");
mVersionString = "2";
loadXml(mService);
assertEquals(1, mService.getDefaultComponents().size());
mDefaults.forEach(pkg -> {
assertTrue(mService.getDefaultComponents().contains(pkg));
});
}
@Test
public void loadDefaults_versionOneWithXMLDefaultsWithActive() throws Exception {
resetComponentsAndPackages();
mDefaults.add(new ComponentName("default", "class"));
mDefaultsString = "xml/class";
mExpectedPrimaryComponentNames.put(0, "package/class");
mVersionString = "1";
loadXml(mService);
assertEquals(mService.getDefaultComponents(),
new ArraySet(Arrays.asList(new ComponentName("xml", "class"))));
}
@Test
public void loadDefaults_versionTwoWithXMLDefaultsWithActive() throws Exception {
resetComponentsAndPackages();
mDefaults.add(new ComponentName("default", "class"));
mDefaultsString = "xml/class";
mExpectedPrimaryComponentNames.put(0, "package/class");
mVersionString = "2";
loadXml(mService);
assertEquals(mService.getDefaultComponents(),
new ArraySet(Arrays.asList(new ComponentName("xml", "class"))));
}
private void resetComponentsAndPackages() {
ArrayMap<Integer, ArrayMap<Integer, String>> empty = new ArrayMap(1);
ArrayMap<Integer, String> emptyPkgs = new ArrayMap(0);
empty.append(mService.mApprovalLevel, emptyPkgs);
mExpectedPrimary = empty;
mExpectedPrimaryComponentNames = emptyPkgs;
mExpectedPrimaryPackages = emptyPkgs;
mExpectedSecondary = empty;
mExpectedSecondaryComponentNames = emptyPkgs;
mExpectedSecondaryPackages = emptyPkgs;
}
private void loadXml(ManagedServices service) throws Exception {
final StringBuffer xml = new StringBuffer();
xml.append("<" + service.getConfig().xmlTag + ">\n");
String xmlTag = service.getConfig().xmlTag;
xml.append("<" + xmlTag
+ (mDefaultsString != null ? " defaults=\"" + mDefaultsString + "\" " : "")
+ (mVersionString != null ? " version=\"" + mVersionString + "\" " : "")
+ ">\n");
for (int userId : mExpectedPrimary.get(service.mApprovalLevel).keySet()) {
xml.append(getXmlEntry(
mExpectedPrimary.get(service.mApprovalLevel).get(userId), userId, true));
@@ -1197,7 +1297,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
+ ManagedServices.ATT_USER_ID + "=\"98\" "
+ ManagedServices.ATT_IS_PRIMARY + "=\"false\" "
+ ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n");
xml.append("</" + service.getConfig().xmlTag + ">");
xml.append("</" + xmlTag + ">");
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
@@ -1224,6 +1324,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
private void addExpectedServices(final ManagedServices service, final List<String> packages,
int userId) {
ManagedServices.Config config = service.getConfig();
when(mPm.queryIntentServicesAsUser(any(), anyInt(), eq(userId))).
thenAnswer(new Answer<List<ResolveInfo>>() {
@Override
@@ -1233,7 +1334,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
Intent invocationIntent = (Intent) args[0];
if (invocationIntent != null) {
if (invocationIntent.getAction().equals(
service.getConfig().serviceInterface)
config.serviceInterface)
&& packages.contains(invocationIntent.getPackage())) {
List<ResolveInfo> dummyServices = new ArrayList<>();
for (int i = 1; i <= 3; i ++) {
@@ -1430,6 +1531,11 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
@Override
protected void loadDefaultsFromConfig() {
mDefaultComponents.addAll(mDefaults);
}
@Override
protected String getRequiredPermission() {
return null;

View File

@@ -72,13 +72,13 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
Object mLock = new Object();
UserInfo mZero = new UserInfo(0, "zero", 0);
UserInfo mTen = new UserInfo(10, "ten", 0);
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
getContext().setMockPackageManager(mPm);
getContext().addMockSystemService(Context.USER_SERVICE, mUm);
mAssistants = spy(mNm.new NotificationAssistants(getContext(), mLock, mUserProfiles, miPm));
@@ -122,7 +122,7 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
@Test
public void testXmlUpgradeExistingApprovedComponents() throws Exception {
String xml = "<enabled_assistants>"
String xml = "<enabled_assistants version=\"2\" defaults=\"b\\b\">"
+ "<service_listing approved=\"b/b\" user=\"10\" primary=\"true\" />"
+ "</enabled_assistants>";

View File

@@ -786,33 +786,16 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
userInfos.add(new UserInfo(0, "", 0));
final ArraySet<ComponentName> validAssistants = new ArraySet<>();
validAssistants.add(ComponentName.unflattenFromString(testComponent));
final String originalComponent = DeviceConfig.getProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE
);
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
testComponent,
false
);
when(mActivityManager.isLowRamDevice()).thenReturn(false);
when(mAssistants.queryPackageForServices(isNull(), anyInt(), anyInt()))
.thenReturn(validAssistants);
when(mAssistants.getDefaultComponents()).thenReturn(new ArraySet<>());
when(mAssistants.getDefaultComponents()).thenReturn(validAssistants);
when(mUm.getEnabledProfiles(anyInt())).thenReturn(userInfos);
mService.setDefaultAssistantForUser(userId);
verify(mAssistants).setPackageOrComponentEnabled(
eq(testComponent), eq(userId), eq(true), eq(true));
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
originalComponent,
false
);
}
@Test
@@ -6299,7 +6282,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.loadDefaultApprovedServices(USER_SYSTEM);
verify(mConditionProviders, times(1)).addDefaultComponentOrPackage("test");
verify(mConditionProviders, times(1)).loadDefaultsFromConfig();
}
// TODO: add tests for the rest of the non-empty cases