Merge "Eanble sending non-A11yTool notification dyanmically" into tm-dev

This commit is contained in:
Ryan Lin
2022-04-11 04:34:50 +00:00
committed by Android (Google) Code Review
5 changed files with 194 additions and 61 deletions

View File

@@ -94,6 +94,7 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
import android.provider.SettingsStringUtil.SettingStringHelper; import android.provider.SettingsStringUtil.SettingStringHelper;
import android.safetycenter.SafetyCenterManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter; import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArraySet; import android.util.ArraySet;
@@ -414,11 +415,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mMainHandler = new MainHandler(mContext.getMainLooper()); mMainHandler = new MainHandler(mContext.getMainLooper());
mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class); mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class);
mPackageManager = mContext.getPackageManager(); mPackageManager = mContext.getPackageManager();
PolicyWarningUIController policyWarningUIController; final PolicyWarningUIController policyWarningUIController = new PolicyWarningUIController(
if (AccessibilitySecurityPolicy.POLICY_WARNING_ENABLED) { mMainHandler, context,
policyWarningUIController = new PolicyWarningUIController(mMainHandler, context, new PolicyWarningUIController.NotificationController(context));
new PolicyWarningUIController.NotificationController(context));
}
mSecurityPolicy = new AccessibilitySecurityPolicy(policyWarningUIController, mContext, mSecurityPolicy = new AccessibilitySecurityPolicy(policyWarningUIController, mContext,
this); this);
mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler, mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
@@ -467,6 +466,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
LocalServices.getService(AppWidgetManagerInternal.class)); LocalServices.getService(AppWidgetManagerInternal.class));
} }
} }
// SafetyCenterService is ready after this phase.
if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
setNonA11yToolNotificationToMatchSafetyCenter();
}
}
private void setNonA11yToolNotificationToMatchSafetyCenter() {
final boolean sendNotification = !mContext.getSystemService(
SafetyCenterManager.class).isSafetyCenterEnabled();
synchronized (mLock) {
mSecurityPolicy.setSendingNonA11yToolNotificationLocked(sendNotification);
}
} }
AccessibilityUserState getCurrentUserState() { AccessibilityUserState getCurrentUserState() {
@@ -722,6 +734,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
} }
} }
}, UserHandle.ALL, intentFilter, null, null); }, UserHandle.ALL, intentFilter, null, null);
final IntentFilter filter = new IntentFilter();
filter.addAction(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED);
final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setNonA11yToolNotificationToMatchSafetyCenter();
}
};
mContext.registerReceiverAsUser(receiver, UserHandle.ALL, filter, null, mMainHandler,
Context.RECEIVER_EXPORTED);
} }
// Called only during settings restore; currently supports only the owner user // Called only during settings restore; currently supports only the owner user

View File

@@ -80,8 +80,6 @@ public class AccessibilitySecurityPolicy {
| AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
| AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
public static final boolean POLICY_WARNING_ENABLED = true;
/** /**
* Methods that should find their way into separate modules, but are still in AMS * Methods that should find their way into separate modules, but are still in AMS
* TODO (b/111889696): Refactoring UserState to AccessibilityUserManager. * TODO (b/111889696): Refactoring UserState to AccessibilityUserManager.
@@ -106,6 +104,7 @@ public class AccessibilitySecurityPolicy {
private AppWidgetManagerInternal mAppWidgetService; private AppWidgetManagerInternal mAppWidgetService;
private AccessibilityWindowManager mAccessibilityWindowManager; private AccessibilityWindowManager mAccessibilityWindowManager;
private int mCurrentUserId = UserHandle.USER_NULL; private int mCurrentUserId = UserHandle.USER_NULL;
private boolean mSendNonA11yToolNotificationEnabled = false;
/** /**
* Constructor for AccessibilityManagerService. * Constructor for AccessibilityManagerService.
@@ -119,7 +118,25 @@ public class AccessibilitySecurityPolicy {
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mPolicyWarningUIController = policyWarningUIController; mPolicyWarningUIController = policyWarningUIController;
mPolicyWarningUIController.setAccessibilityPolicyManager(this); }
/**
* Enables sending the notification for non-AccessibilityTool services with the given state.
*
*/
public void setSendingNonA11yToolNotificationLocked(boolean enable) {
if (enable == mSendNonA11yToolNotificationEnabled) {
return;
}
mSendNonA11yToolNotificationEnabled = enable;
mPolicyWarningUIController.enableSendingNonA11yToolNotification(enable);
if (enable) {
for (int i = 0; i < mNonA11yCategoryServices.size(); i++) {
final ComponentName service = mNonA11yCategoryServices.valueAt(i);
mPolicyWarningUIController.onNonA11yCategoryServiceBound(mCurrentUserId, service);
}
}
} }
/** /**
@@ -725,9 +742,6 @@ public class AccessibilitySecurityPolicy {
*/ */
public void onBoundServicesChangedLocked(int userId, public void onBoundServicesChangedLocked(int userId,
ArrayList<AccessibilityServiceConnection> boundServices) { ArrayList<AccessibilityServiceConnection> boundServices) {
if (!POLICY_WARNING_ENABLED) {
return;
}
if (mAccessibilityUserManager.getCurrentUserIdLocked() != userId) { if (mAccessibilityUserManager.getCurrentUserIdLocked() != userId) {
return; return;
} }
@@ -742,7 +756,9 @@ public class AccessibilitySecurityPolicy {
if (mNonA11yCategoryServices.contains(service)) { if (mNonA11yCategoryServices.contains(service)) {
mNonA11yCategoryServices.remove(service); mNonA11yCategoryServices.remove(service);
} else { } else {
mPolicyWarningUIController.onNonA11yCategoryServiceBound(userId, service); if (mSendNonA11yToolNotificationEnabled) {
mPolicyWarningUIController.onNonA11yCategoryServiceBound(userId, service);
}
} }
} }
} }
@@ -763,14 +779,11 @@ public class AccessibilitySecurityPolicy {
* @param enabledServices The enabled services * @param enabledServices The enabled services
*/ */
public void onSwitchUserLocked(int userId, Set<ComponentName> enabledServices) { public void onSwitchUserLocked(int userId, Set<ComponentName> enabledServices) {
if (!POLICY_WARNING_ENABLED) {
return;
}
if (mCurrentUserId == userId) { if (mCurrentUserId == userId) {
return; return;
} }
mPolicyWarningUIController.onSwitchUser(userId,
mPolicyWarningUIController.onSwitchUserLocked(userId, enabledServices); new ArraySet<>(enabledServices));
for (int i = 0; i < mNonA11yCategoryServices.size(); i++) { for (int i = 0; i < mNonA11yCategoryServices.size(); i++) {
mPolicyWarningUIController.onNonA11yCategoryServiceUnbound(mCurrentUserId, mPolicyWarningUIController.onNonA11yCategoryServiceUnbound(mCurrentUserId,
@@ -786,15 +799,11 @@ public class AccessibilitySecurityPolicy {
* @param userId The user id * @param userId The user id
* @param enabledServices The enabled services * @param enabledServices The enabled services
*/ */
public void onEnabledServicesChangedLocked(int userId, public void onEnabledServicesChangedLocked(int userId, Set<ComponentName> enabledServices) {
Set<ComponentName> enabledServices) {
if (!POLICY_WARNING_ENABLED) {
return;
}
if (mAccessibilityUserManager.getCurrentUserIdLocked() != userId) { if (mAccessibilityUserManager.getCurrentUserIdLocked() != userId) {
return; return;
} }
mPolicyWarningUIController.onEnabledServicesChanged(userId,
mPolicyWarningUIController.onEnabledServicesChangedLocked(userId, enabledServices); new ArraySet<>(enabledServices));
} }
} }

View File

@@ -53,6 +53,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.ImageUtils; import com.android.internal.util.ImageUtils;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@@ -96,24 +97,23 @@ public class PolicyWarningUIController {
filter.addAction(ACTION_DISMISS_NOTIFICATION); filter.addAction(ACTION_DISMISS_NOTIFICATION);
mContext.registerReceiver(mNotificationController, filter, mContext.registerReceiver(mNotificationController, filter,
Manifest.permission.MANAGE_ACCESSIBILITY, mMainHandler, Context.RECEIVER_EXPORTED); Manifest.permission.MANAGE_ACCESSIBILITY, mMainHandler, Context.RECEIVER_EXPORTED);
}
protected void setAccessibilityPolicyManager(
AccessibilitySecurityPolicy accessibilitySecurityPolicy) {
mNotificationController.setAccessibilityPolicyManager(accessibilitySecurityPolicy);
} }
/** /**
* Updates enabled accessibility services and notified accessibility services after switching * Updates enabled accessibility services and notified accessibility services after switching
* to another user. * to another user.
* *
* @param enabledServices The current enabled services * @param enabledServices the current enabled services
*/ */
public void onSwitchUserLocked(int userId, Set<ComponentName> enabledServices) { public void onSwitchUser(int userId, Set<ComponentName> enabledServices) {
mMainHandler.sendMessage(
obtainMessage(this::onSwitchUserInternal, userId, enabledServices));
}
private void onSwitchUserInternal(int userId, Set<ComponentName> enabledServices) {
mEnabledA11yServices.clear(); mEnabledA11yServices.clear();
mEnabledA11yServices.addAll(enabledServices); mEnabledA11yServices.addAll(enabledServices);
mMainHandler.sendMessage(obtainMessage(mNotificationController::onSwitchUser, userId)); mNotificationController.onSwitchUser(userId);
} }
/** /**
@@ -122,10 +122,14 @@ public class PolicyWarningUIController {
* setting {@link Settings.Secure#ENABLED_ACCESSIBILITY_SERVICES} changed. * setting {@link Settings.Secure#ENABLED_ACCESSIBILITY_SERVICES} changed.
* *
* @param userId The user id * @param userId The user id
* @param enabledServices The enabled services * @param enabledServices The enabled services set
*/ */
public void onEnabledServicesChangedLocked(int userId, public void onEnabledServicesChanged(int userId, Set<ComponentName> enabledServices) {
Set<ComponentName> enabledServices) { mMainHandler.sendMessage(
obtainMessage(this::onEnabledServicesChangedInternal, userId, enabledServices));
}
void onEnabledServicesChangedInternal(int userId, Set<ComponentName> enabledServices) {
final ArraySet<ComponentName> disabledServices = new ArraySet<>(mEnabledA11yServices); final ArraySet<ComponentName> disabledServices = new ArraySet<>(mEnabledA11yServices);
disabledServices.removeAll(enabledServices); disabledServices.removeAll(enabledServices);
mEnabledA11yServices.clear(); mEnabledA11yServices.clear();
@@ -187,6 +191,18 @@ public class PolicyWarningUIController {
return intent; return intent;
} }
/**
* Enables to send the notification for non-Accessibility services.
*/
public void enableSendingNonA11yToolNotification(boolean enable) {
mMainHandler.sendMessage(
obtainMessage(this::enableSendingNonA11yToolNotificationInternal, enable));
}
private void enableSendingNonA11yToolNotificationInternal(boolean enable) {
mNotificationController.setSendingNotification(enable);
}
/** A sub class to handle notifications and settings on the main thread. */ /** A sub class to handle notifications and settings on the main thread. */
@MainThread @MainThread
public static class NotificationController extends BroadcastReceiver { public static class NotificationController extends BroadcastReceiver {
@@ -194,22 +210,19 @@ public class PolicyWarningUIController {
/** All accessibility services which are notified to the user by the policy warning rule. */ /** All accessibility services which are notified to the user by the policy warning rule. */
private final ArraySet<ComponentName> mNotifiedA11yServices = new ArraySet<>(); private final ArraySet<ComponentName> mNotifiedA11yServices = new ArraySet<>();
/** The component name of sent notifications. */
private final List<ComponentName> mSentA11yServiceNotification = new ArrayList<>();
private final NotificationManager mNotificationManager; private final NotificationManager mNotificationManager;
private final Context mContext; private final Context mContext;
private int mCurrentUserId; private int mCurrentUserId;
private AccessibilitySecurityPolicy mAccessibilitySecurityPolicy; private boolean mSendNotification;
public NotificationController(Context context) { public NotificationController(Context context) {
mContext = context; mContext = context;
mNotificationManager = mContext.getSystemService(NotificationManager.class); mNotificationManager = mContext.getSystemService(NotificationManager.class);
} }
protected void setAccessibilityPolicyManager(
AccessibilitySecurityPolicy accessibilitySecurityPolicy) {
mAccessibilitySecurityPolicy = accessibilitySecurityPolicy;
}
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
final String action = intent.getAction(); final String action = intent.getAction();
@@ -238,15 +251,18 @@ public class PolicyWarningUIController {
} }
mNotificationManager.cancel(componentName.flattenToShortString(), mNotificationManager.cancel(componentName.flattenToShortString(),
NOTE_A11Y_VIEW_AND_CONTROL_ACCESS); NOTE_A11Y_VIEW_AND_CONTROL_ACCESS);
mSentA11yServiceNotification.remove(componentName);
onNotificationCanceled(userId, componentName); onNotificationCanceled(userId, componentName);
} else if (ACTION_DISMISS_NOTIFICATION.equals(action)) { } else if (ACTION_DISMISS_NOTIFICATION.equals(action)) {
mSentA11yServiceNotification.remove(componentName);
onNotificationCanceled(userId, componentName); onNotificationCanceled(userId, componentName);
} }
} }
protected void onSwitchUser(int userId) { protected void onSwitchUser(int userId) {
mCurrentUserId = userId; cancelSentNotifications();
mNotifiedA11yServices.clear(); mNotifiedA11yServices.clear();
mCurrentUserId = userId;
mNotifiedA11yServices.addAll(readNotifiedServiceList(userId)); mNotifiedA11yServices.addAll(readNotifiedServiceList(userId));
} }
@@ -258,10 +274,11 @@ public class PolicyWarningUIController {
} }
private boolean trySendNotification(int userId, ComponentName componentName) { private boolean trySendNotification(int userId, ComponentName componentName) {
if (!AccessibilitySecurityPolicy.POLICY_WARNING_ENABLED) { if (userId != mCurrentUserId) {
return false; return false;
} }
if (userId != mCurrentUserId) {
if (!mSendNotification) {
return false; return false;
} }
@@ -344,6 +361,7 @@ public class PolicyWarningUIController {
mNotificationManager.notify(serviceComponentName.flattenToShortString(), mNotificationManager.notify(serviceComponentName.flattenToShortString(),
NOTE_A11Y_VIEW_AND_CONTROL_ACCESS, NOTE_A11Y_VIEW_AND_CONTROL_ACCESS,
notificationBuilder.build()); notificationBuilder.build());
mSentA11yServiceNotification.add(serviceComponentName);
} }
private ArraySet<ComponentName> readNotifiedServiceList(int userId) { private ArraySet<ComponentName> readNotifiedServiceList(int userId) {
@@ -393,5 +411,15 @@ public class PolicyWarningUIController {
return accessibilityManager.getEnabledAccessibilityServiceList( return accessibilityManager.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK); AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
} }
private void cancelSentNotifications() {
mSentA11yServiceNotification.forEach(componentName -> mNotificationManager.cancel(
componentName.flattenToShortString(), NOTE_A11Y_VIEW_AND_CONTROL_ACCESS));
mSentA11yServiceNotification.clear();
}
void setSendingNotification(boolean enable) {
mSendNotification = enable;
}
} }
} }

View File

@@ -158,6 +158,7 @@ public class AccessibilitySecurityPolicyTest {
mA11ySecurityPolicy = new AccessibilitySecurityPolicy( mA11ySecurityPolicy = new AccessibilitySecurityPolicy(
mPolicyWarningUIController, mContext, mMockA11yUserManager); mPolicyWarningUIController, mContext, mMockA11yUserManager);
mA11ySecurityPolicy.setSendingNonA11yToolNotificationLocked(true);
mA11ySecurityPolicy.setAccessibilityWindowManager(mMockA11yWindowManager); mA11ySecurityPolicy.setAccessibilityWindowManager(mMockA11yWindowManager);
mA11ySecurityPolicy.setAppWidgetManager(mMockAppWidgetManager); mA11ySecurityPolicy.setAppWidgetManager(mMockAppWidgetManager);
mA11ySecurityPolicy.onSwitchUserLocked(TEST_USER_ID, new HashSet<>()); mA11ySecurityPolicy.onSwitchUserLocked(TEST_USER_ID, new HashSet<>());
@@ -653,11 +654,18 @@ public class AccessibilitySecurityPolicyTest {
mA11ySecurityPolicy.onSwitchUserLocked(newUserId, new HashSet<>()); mA11ySecurityPolicy.onSwitchUserLocked(newUserId, new HashSet<>());
verify(mPolicyWarningUIController).onSwitchUserLocked(eq(newUserId), eq(new HashSet<>())); verify(mPolicyWarningUIController).onSwitchUser(eq(newUserId), eq(new HashSet<>()));
verify(mPolicyWarningUIController).onNonA11yCategoryServiceUnbound(eq(TEST_USER_ID), verify(mPolicyWarningUIController).onNonA11yCategoryServiceUnbound(eq(TEST_USER_ID),
eq(TEST_COMPONENT_NAME)); eq(TEST_COMPONENT_NAME));
} }
@Test
public void enableSendingNonA11yToolNotificationLocked_propagateToPolicyWarningController() {
mA11ySecurityPolicy.setSendingNonA11yToolNotificationLocked(true);
verify(mPolicyWarningUIController).enableSendingNonA11yToolNotification(true);
}
private void initServiceInfoAndConnection(ComponentName componentName, private void initServiceInfoAndConnection(ComponentName componentName,
AccessibilityServiceConnection connection, AccessibilityServiceConnection connection,
boolean isAccessibilityTool) { boolean isAccessibilityTool) {

View File

@@ -29,6 +29,7 @@ import static junit.framework.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -46,12 +47,16 @@ import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.testing.TestableContext; import android.testing.TestableContext;
import android.util.ArraySet;
import com.google.common.collect.ImmutableSet;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.util.ArrayList; import java.util.ArrayList;
@@ -67,6 +72,8 @@ public class PolicyWarningUIControllerTest {
private static final ComponentName TEST_COMPONENT_NAME = new ComponentName( private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(
"com.android.server.accessibility", "PolicyWarningUIControllerTest"); "com.android.server.accessibility", "PolicyWarningUIControllerTest");
private static final ComponentName TEST_COMPONENT_NAME2 = new ComponentName(
"com.android.server.accessibility", "nonAccessibilityToolService");
private final List<AccessibilityServiceInfo> mEnabledServiceList = new ArrayList<>(); private final List<AccessibilityServiceInfo> mEnabledServiceList = new ArrayList<>();
@Rule @Rule
@@ -79,15 +86,9 @@ public class PolicyWarningUIControllerTest {
@Mock @Mock
private StatusBarManager mStatusBarManager; private StatusBarManager mStatusBarManager;
@Mock @Mock
private AccessibilityServiceInfo mMockA11yServiceInfo;
@Mock
private ResolveInfo mMockResolveInfo;
@Mock
private ServiceInfo mMockServiceInfo; private ServiceInfo mMockServiceInfo;
@Mock @Mock
private Context mSpyContext; private Context mSpyContext;
@Mock
private AccessibilitySecurityPolicy mAccessibilitySecurityPolicy;
private PolicyWarningUIController mPolicyWarningUIController; private PolicyWarningUIController mPolicyWarningUIController;
private FakeNotificationController mFakeNotificationController; private FakeNotificationController mFakeNotificationController;
@@ -102,21 +103,18 @@ public class PolicyWarningUIControllerTest {
mPolicyWarningUIController = new PolicyWarningUIController( mPolicyWarningUIController = new PolicyWarningUIController(
getInstrumentation().getTargetContext().getMainThreadHandler(), mContext, getInstrumentation().getTargetContext().getMainThreadHandler(), mContext,
mFakeNotificationController); mFakeNotificationController);
mPolicyWarningUIController.setAccessibilityPolicyManager(mAccessibilitySecurityPolicy);
mPolicyWarningUIController.onSwitchUserLocked(TEST_USER_ID, new HashSet<>());
mEnabledServiceList.clear(); mEnabledServiceList.clear();
Settings.Secure.putStringForUser(mContext.getContentResolver(), Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.NOTIFIED_NON_ACCESSIBILITY_CATEGORY_SERVICES, Settings.Secure.NOTIFIED_NON_ACCESSIBILITY_CATEGORY_SERVICES,
"", TEST_USER_ID); "", TEST_USER_ID);
mPolicyWarningUIController.enableSendingNonA11yToolNotification(true);
mPolicyWarningUIController.onSwitchUser(TEST_USER_ID, new HashSet<>());
getInstrumentation().waitForIdleSync();
} }
@Test @Test
public void receiveActionSendNotification_isNonA11yCategoryService_sendNotification() { public void receiveActionSendNotification_isNonA11yCategoryService_sendNotification() {
mEnabledServiceList.add(mMockA11yServiceInfo); addEnabledServiceInfo(TEST_COMPONENT_NAME, false);
mMockResolveInfo.serviceInfo = mMockServiceInfo;
when(mMockA11yServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
when(mMockA11yServiceInfo.getComponentName()).thenReturn(TEST_COMPONENT_NAME);
when(mMockA11yServiceInfo.isAccessibilityTool()).thenReturn(false);
mFakeNotificationController.onReceive(mContext, mFakeNotificationController.onReceive(mContext,
PolicyWarningUIController.createIntent(mContext, TEST_USER_ID, PolicyWarningUIController.createIntent(mContext, TEST_USER_ID,
@@ -127,6 +125,39 @@ public class PolicyWarningUIControllerTest {
eq(NOTE_A11Y_VIEW_AND_CONTROL_ACCESS), any(Notification.class)); eq(NOTE_A11Y_VIEW_AND_CONTROL_ACCESS), any(Notification.class));
} }
@Test
public void receiveActionSendNotification_sendNotificationDisabled_doNothing() {
mPolicyWarningUIController.enableSendingNonA11yToolNotification(false);
addEnabledServiceInfo(TEST_COMPONENT_NAME, false);
mFakeNotificationController.onReceive(mContext,
PolicyWarningUIController.createIntent(mContext, TEST_USER_ID,
PolicyWarningUIController.ACTION_SEND_NOTIFICATION,
TEST_COMPONENT_NAME));
verify(mNotificationManager, never()).notify(eq(TEST_COMPONENT_NAME.flattenToShortString()),
eq(NOTE_A11Y_VIEW_AND_CONTROL_ACCESS), any(Notification.class));
}
@Test
public void receiveActionSendNotificationWithNotifiedService_doNothing() {
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.NOTIFIED_NON_ACCESSIBILITY_CATEGORY_SERVICES,
TEST_COMPONENT_NAME.flattenToShortString(), TEST_USER_ID);
mEnabledServiceList.clear();
mPolicyWarningUIController.onSwitchUser(TEST_USER_ID, new HashSet<>());
getInstrumentation().waitForIdleSync();
addEnabledServiceInfo(TEST_COMPONENT_NAME, false);
mFakeNotificationController.onReceive(mContext,
PolicyWarningUIController.createIntent(mContext, TEST_USER_ID,
PolicyWarningUIController.ACTION_SEND_NOTIFICATION,
TEST_COMPONENT_NAME));
verify(mNotificationManager, never()).notify(eq(TEST_COMPONENT_NAME.flattenToShortString()),
eq(NOTE_A11Y_VIEW_AND_CONTROL_ACCESS), any(Notification.class));
}
@Test @Test
public void receiveActionA11ySettings_launchA11ySettingsAndDismissNotification() { public void receiveActionA11ySettings_launchA11ySettingsAndDismissNotification() {
mFakeNotificationController.onReceive(mContext, mFakeNotificationController.onReceive(mContext,
@@ -154,11 +185,11 @@ public class PolicyWarningUIControllerTest {
public void onEnabledServicesChangedLocked_serviceDisabled_removedFromNotifiedSettings() { public void onEnabledServicesChangedLocked_serviceDisabled_removedFromNotifiedSettings() {
final Set<ComponentName> enabledServices = new HashSet<>(); final Set<ComponentName> enabledServices = new HashSet<>();
enabledServices.add(TEST_COMPONENT_NAME); enabledServices.add(TEST_COMPONENT_NAME);
mPolicyWarningUIController.onEnabledServicesChangedLocked(TEST_USER_ID, enabledServices); mPolicyWarningUIController.onEnabledServicesChanged(TEST_USER_ID, enabledServices);
getInstrumentation().waitForIdleSync(); getInstrumentation().waitForIdleSync();
receiveActionDismissNotification_addToNotifiedSettings(); receiveActionDismissNotification_addToNotifiedSettings();
mPolicyWarningUIController.onEnabledServicesChangedLocked(TEST_USER_ID, new HashSet<>()); mPolicyWarningUIController.onEnabledServicesChanged(TEST_USER_ID, new HashSet<>());
getInstrumentation().waitForIdleSync(); getInstrumentation().waitForIdleSync();
assertNotifiedSettingsEqual(TEST_USER_ID, ""); assertNotifiedSettingsEqual(TEST_USER_ID, "");
@@ -185,6 +216,29 @@ public class PolicyWarningUIControllerTest {
PolicyWarningUIController.ACTION_SEND_NOTIFICATION, TEST_COMPONENT_NAME))); PolicyWarningUIController.ACTION_SEND_NOTIFICATION, TEST_COMPONENT_NAME)));
} }
@Test
public void onSwitchUserLocked_hasAlarmAndSentNotification_cancelNotification() {
addEnabledServiceInfo(TEST_COMPONENT_NAME2, false);
final Set<ComponentName> enabledNonA11yServices = new ArraySet<>();
enabledNonA11yServices.add(TEST_COMPONENT_NAME);
enabledNonA11yServices.add(TEST_COMPONENT_NAME2);
mPolicyWarningUIController.onEnabledServicesChanged(TEST_USER_ID,
enabledNonA11yServices);
mPolicyWarningUIController.onNonA11yCategoryServiceBound(TEST_USER_ID, TEST_COMPONENT_NAME);
mFakeNotificationController.onReceive(mContext,
PolicyWarningUIController.createIntent(mContext, TEST_USER_ID,
PolicyWarningUIController.ACTION_SEND_NOTIFICATION,
TEST_COMPONENT_NAME2));
getInstrumentation().waitForIdleSync();
mPolicyWarningUIController.onSwitchUser(TEST_USER_ID,
ImmutableSet.copyOf(new ArraySet<>()));
getInstrumentation().waitForIdleSync();
verify(mNotificationManager).cancel(TEST_COMPONENT_NAME2.flattenToShortString(),
NOTE_A11Y_VIEW_AND_CONTROL_ACCESS);
}
private void assertNotifiedSettingsEqual(int userId, String settingString) { private void assertNotifiedSettingsEqual(int userId, String settingString) {
final String notifiedServicesSetting = Settings.Secure.getStringForUser( final String notifiedServicesSetting = Settings.Secure.getStringForUser(
mContext.getContentResolver(), mContext.getContentResolver(),
@@ -205,6 +259,17 @@ public class PolicyWarningUIControllerTest {
verify(mStatusBarManager).collapsePanels(); verify(mStatusBarManager).collapsePanels();
} }
private void addEnabledServiceInfo(ComponentName componentName, boolean isAccessibilityTool) {
final AccessibilityServiceInfo a11yServiceInfo = Mockito.mock(
AccessibilityServiceInfo.class);
when(a11yServiceInfo.getComponentName()).thenReturn(componentName);
when(a11yServiceInfo.isAccessibilityTool()).thenReturn(isAccessibilityTool);
final ResolveInfo resolveInfo = Mockito.mock(ResolveInfo.class);
when(a11yServiceInfo.getResolveInfo()).thenReturn(resolveInfo);
resolveInfo.serviceInfo = mMockServiceInfo;
mEnabledServiceList.add(a11yServiceInfo);
}
private class A11yTestableContext extends TestableContext { private class A11yTestableContext extends TestableContext {
A11yTestableContext(Context base) { A11yTestableContext(Context base) {
super(base); super(base);