Preconditions.checkNotNull(channel);
ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- checkHasCompanionDevice(info);
+ if (!hasCompanionDevice(info)) {
+ throw new SecurityException(info + " does not have access");
+ }
int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
updateNotificationChannelInt(pkg, uid, channel, true);
public ParceledListSlice<NotificationChannel> getNotificationChannelsFromPrivilegedListener(
INotificationListener token, String pkg) throws RemoteException {
ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- checkHasCompanionDevice(info);
+ if (!hasCompanionDevice(info)) {
+ throw new SecurityException(info + " does not have access");
+ }
int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
return mRankingHelper.getNotificationChannels(pkg, uid, false /* includeDeleted */);
getNotificationChannelGroupsFromPrivilegedListener(
INotificationListener token, String pkg) throws RemoteException {
ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- checkHasCompanionDevice(info);
+ if (!hasCompanionDevice(info)) {
+ throw new SecurityException(info + " does not have access");
+ }
List<NotificationChannelGroup> groups = new ArrayList<>();
int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
channels, overridePeople, snoozeCriteria, showBadge);
}
- private void checkHasCompanionDevice(ManagedServiceInfo info) throws RemoteException {
+ boolean hasCompanionDevice(ManagedServiceInfo info) {
if (mCompanionManager == null) {
mCompanionManager = ICompanionDeviceManager.Stub.asInterface(
ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE));
}
- if (ArrayUtils.isEmpty(mCompanionManager.getAssociations(
- info.component.getPackageName(), info.userid))) {
- throw new SecurityException("Disallowed call from " + info.component);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ List<String> associations = mCompanionManager.getAssociations(
+ info.component.getPackageName(), info.userid);
+ if (!ArrayUtils.isEmpty(associations)) {
+ return true;
+ }
+ } catch (SecurityException se) {
+ // Not a privileged listener
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Cannot reach companion device service", re);
+ } catch (Exception e) {
+ Slog.e(TAG, "Cannot verify listener " + info, e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
+ return false;
}
private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
return;
}
for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) {
continue;
}
- try {
- checkHasCompanionDevice(serviceInfo);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyNotificationChannelChanged(serviceInfo, pkg, channel,
- modificationType);
- }
- });
- } catch (SecurityException se) {
- // Not a privileged listener; do not notify
- } catch (RemoteException e) {
- Slog.e(TAG, "Cannot reach companion device service", e);
+ if (!hasCompanionDevice(serviceInfo)) {
+ continue;
}
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyNotificationChannelChanged(serviceInfo, pkg, channel,
+ modificationType);
+ }
+ });
}
}
return;
}
for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) {
continue;
}
- try {
- checkHasCompanionDevice(serviceInfo);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyNotificationChannelGroupChanged(serviceInfo, pkg, group,
- modificationType);
- }
- });
- } catch (SecurityException se) {
- // Not a privileged listener; do not notify
- } catch (RemoteException e) {
- Slog.e(TAG, "Cannot reach companion device service", e);
+ if (!hasCompanionDevice(serviceInfo)) {
+ continue;
}
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyNotificationChannelGroupChanged(serviceInfo, pkg, group,
+ modificationType);
+ }
+ });
}
}
import java.util.Arrays;
import java.util.List;
-import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
private NotificationManagerService mNotificationManagerService;
private INotificationManager mBinderService;
private NotificationManagerInternal mInternalService;
- private IPackageManager mPackageManager = mock(IPackageManager.class);
- private final PackageManager mPackageManagerClient = mock(PackageManager.class);
+ @Mock
+ private IPackageManager mPackageManager;
+ @Mock
+ private PackageManager mPackageManagerClient;
private Context mContext = InstrumentationRegistry.getTargetContext();
private final String PKG = mContext.getPackageName();
private TestableLooper mTestableLooper;
- private final RankingHelper mRankingHelper = mock(RankingHelper.class);
+ @Mock
+ private RankingHelper mRankingHelper;
private NotificationChannel mTestNotificationChannel = new NotificationChannel(
TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
- private NotificationManagerService.NotificationListeners mNotificationListeners =
- mock(NotificationManagerService.NotificationListeners.class);
- private ManagedServices.ManagedServiceInfo mListener =
- mNotificationListeners.new ManagedServiceInfo(
- null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
- private ICompanionDeviceManager mCompanionMgr = mock(ICompanionDeviceManager.class);
+ @Mock
+ private NotificationManagerService.NotificationListeners mNotificationListeners;
+ private ManagedServices.ManagedServiceInfo mListener;
+ @Mock private ICompanionDeviceManager mCompanionMgr;
// Use a Testable subclass so we can simulate calls from the system without failing.
private static class TestableNotificationManagerService extends NotificationManagerService {
@Before
@UiThreadTest
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
mNotificationManagerService = new TestableNotificationManagerService(mContext);
// MockPackageManager - default returns ApplicationInfo with matching calling UID
// Use this testable looper.
mTestableLooper = new TestableLooper(false);
+ mListener = mNotificationListeners.new ManagedServiceInfo(
+ null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr);
verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
}
+
+ @Test
+ @UiThreadTest
+ public void testHasCompanionDevice_failure() throws Exception {
+ when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
+ new IllegalArgumentException());
+ mNotificationManagerService.hasCompanionDevice(mListener);
+ }
}