diff options
27 files changed, 558 insertions, 337 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 3553748e5004..b949ed9d6079 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3103,11 +3103,18 @@ public class DevicePolicyManager { } } - /** @hide */ - public void resetNewUserDisclaimer() { + /** + * Acknoledges that the new managed user disclaimer was viewed by the (human) user + * so that {@link #ACTION_SHOW_NEW_USER_DISCLAIMER broadcast} is not sent again the next time + * this user is switched to. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + public void acknowledgeNewUserDisclaimer() { if (mService != null) { try { - mService.resetNewUserDisclaimer(); + mService.acknowledgeNewUserDisclaimer(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -5673,7 +5680,7 @@ public class DevicePolicyManager { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SHOW_NEW_USER_DISCLAIMER = - "android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER"; + "android.app.action.SHOW_NEW_USER_DISCLAIMER"; /** * Widgets are enabled in keyguard diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 7c7478bdb41f..a2863bdfc35d 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -264,7 +264,7 @@ interface IDevicePolicyManager { int getLogoutUserId(); void clearLogoutUser(); List<UserHandle> getSecondaryUsers(in ComponentName who); - void resetNewUserDisclaimer(); + void acknowledgeNewUserDisclaimer(); void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index f525315dd5fa..2ad836e54b3f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -703,7 +703,7 @@ <protected-broadcast android:name="android.scheduling.action.REBOOT_READY" /> <protected-broadcast android:name="android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED" /> <protected-broadcast android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" /> - <protected-broadcast android:name="android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER" /> + <protected-broadcast android:name="android.app.action.SHOW_NEW_USER_DISCLAIMER" /> <!-- ====================================================================== --> <!-- RUNTIME PERMISSIONS --> diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index a383c1e2b680..326161b26134 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -164,6 +164,31 @@ public class InfoMediaManager extends MediaManager { return sessionInfos.get(sessionInfos.size() - 1); } + boolean isRoutingSessionAvailableForVolumeControl() { + if (mVolumeAdjustmentForRemoteGroupSessions) { + return true; + } + List<RoutingSessionInfo> sessions = + mRouterManager.getRoutingSessions(mPackageName); + boolean foundNonSystemSession = false; + boolean isGroup = false; + for (RoutingSessionInfo session : sessions) { + if (!session.isSystemSession()) { + foundNonSystemSession = true; + int selectedRouteCount = session.getSelectedRoutes().size(); + if (selectedRouteCount > 1) { + isGroup = true; + break; + } + } + } + if (!foundNonSystemSession) { + Log.d(TAG, "No routing session for " + mPackageName); + return false; + } + return !isGroup; + } + /** * Remove a {@code device} from current media. * diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java index d29d8958dad7..9092024cd457 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java @@ -196,6 +196,14 @@ public class LocalMediaManager implements BluetoothCallback { } /** + * Returns if the media session is available for volume control. + * @return True if this media session is available for colume control, false otherwise. + */ + public boolean isMediaSessionAvailableForVolumeControl() { + return mInfoMediaManager.isRoutingSessionAvailableForVolumeControl(); + } + + /** * Start scan connected MediaDevice */ public void startScan() { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index befb648152d4..789ad6223e79 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -118,9 +118,11 @@ public class DozeMachine { switch (this) { case UNINITIALIZED: case INITIALIZED: - case DOZE_REQUEST_PULSE: return parameters.shouldControlScreenOff() ? Display.STATE_ON : Display.STATE_OFF; + case DOZE_REQUEST_PULSE: + return parameters.getDisplayNeedsBlanking() ? Display.STATE_OFF + : Display.STATE_ON; case DOZE_AOD_PAUSED: case DOZE: return Display.STATE_OFF; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 36319380ad50..52db1bd00c8e 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -105,17 +105,7 @@ public class DozeScreenState implements DozeMachine.Part { updateUdfpsController(); if (mUdfpsController == null) { - mAuthController.addCallback(new AuthController.Callback() { - @Override - public void onAllAuthenticatorsRegistered() { - updateUdfpsController(); - } - - @Override - public void onEnrollmentsChanged() { - updateUdfpsController(); - } - }); + mAuthController.addCallback(mAuthControllerCallback); } } @@ -128,6 +118,11 @@ public class DozeScreenState implements DozeMachine.Part { } @Override + public void destroy() { + mAuthController.removeCallback(mAuthControllerCallback); + } + + @Override public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { int screenState = newState.screenState(mParameters); mDozeHost.cancelGentleSleep(); @@ -222,4 +217,16 @@ public class DozeScreenState implements DozeMachine.Part { mWakeLock.setAcquired(false); } } + + private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() { + @Override + public void onAllAuthenticatorsRegistered() { + updateUdfpsController(); + } + + @Override + public void onEnrollmentsChanged() { + updateUdfpsController(); + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index c8cd43287c99..a7640ff951c8 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -28,6 +28,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroupOverlay import androidx.annotation.VisibleForTesting +import com.android.keyguard.KeyguardViewController import com.android.systemui.R import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton @@ -39,7 +40,6 @@ import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.stack.StackStateAnimator import com.android.systemui.statusbar.phone.KeyguardBypassController -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.Utils @@ -82,7 +82,7 @@ class MediaHierarchyManager @Inject constructor( private val notifLockscreenUserManager: NotificationLockscreenUserManager, configurationController: ConfigurationController, wakefulnessLifecycle: WakefulnessLifecycle, - private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager + private val keyguardViewController: KeyguardViewController ) { /** @@ -998,7 +998,7 @@ class MediaHierarchyManager @Inject constructor( private fun isLockScreenVisibleToUser(): Boolean { return !statusBarStateController.isDozing && - !statusBarKeyguardViewManager.isBouncerShowing && + !keyguardViewController.isBouncerShowing && statusBarStateController.state == StatusBarState.KEYGUARD && notifLockscreenUserManager.shouldShowLockscreenNotifications() && statusBarStateController.isExpanded && @@ -1007,7 +1007,7 @@ class MediaHierarchyManager @Inject constructor( private fun isLockScreenShadeVisibleToUser(): Boolean { return !statusBarStateController.isDozing && - !statusBarKeyguardViewManager.isBouncerShowing && + !keyguardViewController.isBouncerShowing && (statusBarStateController.state == StatusBarState.SHADE_LOCKED || (statusBarStateController.state == StatusBarState.KEYGUARD && qsExpanded)) } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index a82e989f70fc..e01916f0abe8 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -111,7 +111,8 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { } mBottomDivider.setVisibility(View.GONE); mCheckBox.setVisibility(View.GONE); - if (currentlyConnected && mController.isActiveRemoteDevice(device)) { + if (currentlyConnected && mController.isActiveRemoteDevice(device) + && mController.getSelectableMediaDevice().size() > 0) { // Init active device layout mAddIcon.setVisibility(View.VISIBLE); mAddIcon.setTransitionAlpha(1); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 9eaedd753394..0d368fa5fb7f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -84,7 +84,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { private final SystemUIDialogManager mDialogManager; private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>(); private final boolean mAboveStatusbar; - private final boolean mVolumeAdjustmentForRemoteGroupSessions; private final NotificationEntryManager mNotificationEntryManager; @VisibleForTesting final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>(); @@ -117,8 +116,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); mUiEventLogger = uiEventLogger; mDialogLaunchAnimator = dialogLaunchAnimator; - mVolumeAdjustmentForRemoteGroupSessions = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions); mDialogManager = dialogManager; } @@ -496,10 +493,15 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { || features.contains(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK)); } + private boolean isPlayBackInfoLocal() { + return mMediaController.getPlaybackInfo() != null + && mMediaController.getPlaybackInfo().getPlaybackType() + == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL; + } + boolean isVolumeControlEnabled(@NonNull MediaDevice device) { - // TODO(b/202500642): Also enable volume control for remote non-group sessions. - return !isActiveRemoteDevice(device) - || mVolumeAdjustmentForRemoteGroupSessions; + return isPlayBackInfoLocal() + || mLocalMediaManager.isMediaSessionAvailableForVolumeControl(); } private final MediaController.Callback mCb = new MediaController.Callback() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index e82e9d284bdd..e348f2ca7b31 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -428,7 +428,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca public void setBrightnessMirrorController( BrightnessMirrorController brightnessMirrorController) { mQSPanelController.setBrightnessMirror(brightnessMirrorController); - mQuickQSPanelController.setBrightnessMirror(brightnessMirrorController); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt deleted file mode 100644 index 65889d792769..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2021 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.qs - -import androidx.annotation.VisibleForTesting -import com.android.systemui.settings.brightness.BrightnessController -import com.android.systemui.settings.brightness.BrightnessSliderController -import com.android.systemui.settings.brightness.MirroredBrightnessController -import com.android.systemui.statusbar.policy.BrightnessMirrorController -import javax.inject.Inject - -/** - * Controls brightness slider in QQS, which is visible only in split shade. It's responsible for - * showing/hiding it when appropriate and (un)registering listeners - */ -class QuickQSBrightnessController @VisibleForTesting constructor( - private val brightnessControllerFactory: () -> BrightnessController -) : MirroredBrightnessController { - - @Inject constructor( - brightnessControllerFactory: BrightnessController.Factory, - brightnessSliderControllerFactory: BrightnessSliderController.Factory, - quickQSPanel: QuickQSPanel - ) : this(brightnessControllerFactory = { - val slider = brightnessSliderControllerFactory.create(quickQSPanel.context, - quickQSPanel) - slider.init() - quickQSPanel.setBrightnessView(slider.rootView) - brightnessControllerFactory.create(slider) - }) - - private var isListening = false - private var brightnessController: BrightnessController? = null - private var mirrorController: BrightnessMirrorController? = null - - fun init(shouldUseSplitNotificationShade: Boolean) { - refreshVisibility(shouldUseSplitNotificationShade) - } - - /** - * Starts/Stops listening for brightness changing events. - * It's fine to call this function even if slider is not visible (which would be the case for - * all small screen devices), it will just do nothing in that case - */ - fun setListening(listening: Boolean) { - if (listening) { - // controller can be null when slider was never shown - if (!isListening && brightnessController != null) { - brightnessController?.registerCallbacks() - isListening = true - } - } else { - brightnessController?.unregisterCallbacks() - isListening = false - } - } - - fun checkRestrictionAndSetEnabled() { - brightnessController?.checkRestrictionAndSetEnabled() - } - - fun refreshVisibility(shouldUseSplitNotificationShade: Boolean) { - if (shouldUseSplitNotificationShade) { - showBrightnessSlider() - } else { - hideBrightnessSlider() - } - } - - override fun setMirror(controller: BrightnessMirrorController) { - mirrorController = controller - mirrorController?.let { brightnessController?.setMirror(it) } - } - - private fun hideBrightnessSlider() { - brightnessController?.hideSlider() - } - - private fun showBrightnessSlider() { - if (brightnessController == null) { - brightnessController = brightnessControllerFactory() - mirrorController?.also { brightnessController?.setMirror(it) } - brightnessController?.registerCallbacks() - isListening = true - } - brightnessController?.showSlider() - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java index 92690c7d1202..fdd764ce7127 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java @@ -30,8 +30,6 @@ import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.customize.QSCustomizerController; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.logging.QSLogger; -import com.android.systemui.settings.brightness.BrightnessMirrorHandler; -import com.android.systemui.statusbar.policy.BrightnessMirrorController; import java.util.ArrayList; import java.util.List; @@ -51,9 +49,6 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> } }; - // brightness is visible only in split shade - private final QuickQSBrightnessController mBrightnessController; - private final BrightnessMirrorHandler mBrightnessMirrorHandler; private final FooterActionsController mFooterActionsController; @Inject @@ -63,13 +58,10 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> @Named(QUICK_QS_PANEL) MediaHost mediaHost, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, DumpManager dumpManager, - QuickQSBrightnessController quickQSBrightnessController, @Named(QQS_FOOTER) FooterActionsController footerActionsController ) { super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, uiEventLogger, qsLogger, dumpManager); - mBrightnessController = quickQSBrightnessController; - mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); mFooterActionsController = footerActionsController; } @@ -79,7 +71,6 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> mMediaHost.setExpansion(0.0f); mMediaHost.setShowsOnlyActiveMedia(true); mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); - mBrightnessController.init(mShouldUseSplitNotificationShade); mFooterActionsController.init(); mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade); } @@ -88,20 +79,17 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> protected void onViewAttached() { super.onViewAttached(); mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener); - mBrightnessMirrorHandler.onQsPanelAttached(); } @Override protected void onViewDetached() { super.onViewDetached(); mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener); - mBrightnessMirrorHandler.onQsPanelDettached(); } @Override void setListening(boolean listening) { super.setListening(listening); - mBrightnessController.setListening(listening); mFooterActionsController.setListening(listening); } @@ -115,14 +103,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> } @Override - public void refreshAllTiles() { - mBrightnessController.checkRestrictionAndSetEnabled(); - super.refreshAllTiles(); - } - - @Override protected void onConfigurationChanged() { - mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade); mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade); } @@ -146,8 +127,4 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> public int getNumQuickTiles() { return mView.getNumQuickTiles(); } - - public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) { - mBrightnessMirrorHandler.setController(brightnessMirrorController); - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java index 8078b6c8bda4..56844292ce4a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java @@ -42,12 +42,14 @@ import static org.mockito.Mockito.when; import android.hardware.display.AmbientDisplayConfiguration; import android.testing.AndroidTestingRunner; import android.testing.UiThreadTest; +import android.view.Display; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.util.wakelock.WakeLockFake; @@ -444,4 +446,20 @@ public class DozeMachineTest extends SysuiTestCase { assertTrue(mServiceFake.requestedWakeup); } + + @Test + public void testDozePulsing_displayRequiresBlanking_screenState() { + DozeParameters dozeParameters = mock(DozeParameters.class); + when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(true); + + assertEquals(Display.STATE_OFF, DOZE_REQUEST_PULSE.screenState(dozeParameters)); + } + + @Test + public void testDozePulsing_displayDoesNotRequireBlanking_screenState() { + DozeParameters dozeParameters = mock(DozeParameters.class); + when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(false); + + assertEquals(Display.STATE_ON, DOZE_REQUEST_PULSE.screenState(dozeParameters)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java index 3e19cc436dca..992a82b6e7fe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java @@ -35,6 +35,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Matchers.anyObject; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; @@ -306,4 +307,11 @@ public class DozeScreenStateTest extends SysuiTestCase { // THEN the display screen state will change assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState); } + + @Test + public void authCallbackRemovedOnDestroy() { + mScreen.destroy(); + + verify(mAuthController).removeCallback(anyObject()); + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt index a3ffb2fe4b8d..7565fe1c5c0e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt @@ -22,6 +22,7 @@ import android.testing.TestableLooper import android.view.ViewGroup import android.widget.FrameLayout import androidx.test.filters.SmallTest +import com.android.keyguard.KeyguardViewController import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq @@ -31,7 +32,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.phone.KeyguardBypassController -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.animation.UniqueObjectHostView @@ -80,7 +80,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock - private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager + private lateinit var keyguardViewController: KeyguardViewController @Mock private lateinit var configurationController: ConfigurationController @Mock @@ -110,7 +110,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { notificationLockscreenUserManager, configurationController, wakefulnessLifecycle, - statusBarKeyguardViewManager) + keyguardViewController) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture()) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt deleted file mode 100644 index de1d86b08785..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2021 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.qs - -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.settings.brightness.BrightnessController -import com.android.systemui.statusbar.policy.BrightnessMirrorController -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.mockito.Mock -import org.mockito.Mockito.times -import org.mockito.Mockito.verify -import org.mockito.Mockito.never -import org.mockito.Mockito.mock -import org.mockito.junit.MockitoJUnit - -@SmallTest -class QuickQSBrightnessControllerTest : SysuiTestCase() { - - @Mock - lateinit var brightnessController: BrightnessController - @get:Rule - val mockito = MockitoJUnit.rule() - - lateinit var quickQSBrightnessController: QuickQSBrightnessController - - @Before - fun setUp() { - quickQSBrightnessController = QuickQSBrightnessController( - brightnessControllerFactory = { brightnessController }) - } - - @Test - fun testSliderIsShownWhenInitializedInSplitShade() { - quickQSBrightnessController.init(shouldUseSplitNotificationShade = true) - - verify(brightnessController).showSlider() - } - - @Test - fun testSliderIsShownWhenRefreshedInSplitShade() { - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - - verify(brightnessController, times(1)).showSlider() - } - - @Test - fun testSliderIsHiddenWhenRefreshedInNonSplitShade() { - // needs to be shown first - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - - verify(brightnessController).hideSlider() - } - - @Test - fun testSliderChangesVisibilityWhenRotating() { - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - verify(brightnessController, times(1)).showSlider() - - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - verify(brightnessController, times(1)).hideSlider() - } - - @Test - fun testCallbacksAreRegisteredOnlyOnce() { - // this flow simulates expanding shade in portrait... - quickQSBrightnessController.setListening(true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - // ... and rotating to landscape/split shade where slider is visible - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - - verify(brightnessController, times(1)).registerCallbacks() - } - - @Test - fun testCallbacksAreRegisteredOnlyOnceWhenRotatingPhone() { - quickQSBrightnessController.setListening(true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - - verify(brightnessController, times(1)).registerCallbacks() - } - - @Test - fun testCallbacksAreNotRegisteredWhenSliderNotVisible() { - quickQSBrightnessController.setListening(true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - - verify(brightnessController, never()).registerCallbacks() - } - - @Test - fun testMirrorIsSetWhenSliderIsShown() { - val mirrorController = mock(BrightnessMirrorController::class.java) - quickQSBrightnessController.setMirror(mirrorController) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - - verify(brightnessController).setMirror(mirrorController) - } -}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt index 59948d310b4f..fb8a6e3d4212 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt @@ -67,8 +67,6 @@ class QuickQSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var tileView: QSTileView @Mock - private lateinit var quickQsBrightnessController: QuickQSBrightnessController - @Mock private lateinit var footerActionsController: FooterActionsController @Captor private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener> @@ -95,7 +93,6 @@ class QuickQSPanelControllerTest : SysuiTestCase() { uiEventLogger, qsLogger, dumpManager, - quickQsBrightnessController, footerActionsController ) @@ -128,13 +125,11 @@ class QuickQSPanelControllerTest : SysuiTestCase() { } @Test - fun testBrightnessAndFooterVisibilityRefreshedWhenConfigurationChanged() { + fun testFooterVisibilityRefreshedWhenConfigurationChanged() { // times(2) because both controller and base controller are registering their listeners verify(quickQSPanel, times(2)).addOnConfigurationChangedListener(captor.capture()) captor.allValues.forEach { it.onConfigurationChange(Configuration.EMPTY) } - - verify(quickQsBrightnessController).refreshVisibility(anyBoolean()) // times(2) because footer visibility is also refreshed on controller init verify(footerActionsController, times(2)).refreshVisibility(anyBoolean()) } diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java index 2c2a2bf24cfd..17215e5ae4ad 100644 --- a/services/core/java/com/android/server/display/BrightnessTracker.java +++ b/services/core/java/com/android/server/display/BrightnessTracker.java @@ -131,6 +131,7 @@ public class BrightnessTracker { private static final int MSG_STOP_SENSOR_LISTENER = 2; private static final int MSG_START_SENSOR_LISTENER = 3; private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4; + private static final int MSG_SENSOR_CHANGED = 5; private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); @@ -158,6 +159,7 @@ public class BrightnessTracker { // These members should only be accessed on the mBgHandler thread. private BroadcastReceiver mBroadcastReceiver; private SensorListener mSensorListener; + private Sensor mLightSensor; private SettingsObserver mSettingsObserver; private DisplayListener mDisplayListener; private boolean mSensorRegistered; @@ -327,6 +329,14 @@ public class BrightnessTracker { m.sendToTarget(); } + /** + * Updates the light sensor to use. + */ + public void setLightSensor(Sensor lightSensor) { + mBgHandler.obtainMessage(MSG_SENSOR_CHANGED, 0 /*unused*/, 0/*unused*/, lightSensor) + .sendToTarget(); + } + private void handleBrightnessChanged(float brightness, boolean userInitiated, float powerBrightnessFactor, boolean isUserSetBrightness, boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId) { @@ -428,13 +438,28 @@ public class BrightnessTracker { } } + private void handleSensorChanged(Sensor lightSensor) { + if (mLightSensor != lightSensor) { + mLightSensor = lightSensor; + stopSensorListener(); + synchronized (mDataCollectionLock) { + mLastSensorReadings.clear(); + } + // Attempt to restart the sensor listener. It will check to see if it should be running + // so there is no need to also check here. + startSensorListener(); + } + } + private void startSensorListener() { if (!mSensorRegistered + && mLightSensor != null + && mAmbientBrightnessStatsTracker != null && mInjector.isInteractive(mContext) && mInjector.isBrightnessModeAutomatic(mContentResolver)) { mAmbientBrightnessStatsTracker.start(); mSensorRegistered = true; - mInjector.registerSensorListener(mContext, mSensorListener, + mInjector.registerSensorListener(mContext, mSensorListener, mLightSensor, mInjector.getBackgroundHandler()); } } @@ -736,6 +761,7 @@ public class BrightnessTracker { pw.println("BrightnessTracker state:"); synchronized (mDataCollectionLock) { pw.println(" mStarted=" + mStarted); + pw.println(" mLightSensor=" + mLightSensor); pw.println(" mLastBatteryLevel=" + mLastBatteryLevel); pw.println(" mLastBrightness=" + mLastBrightness); pw.println(" mLastSensorReadings.size=" + mLastSensorReadings.size()); @@ -1017,6 +1043,9 @@ public class BrightnessTracker { disableColorSampling(); } break; + case MSG_SENSOR_CHANGED: + handleSensorChanged((Sensor) msg.obj); + break; } } @@ -1045,9 +1074,8 @@ public class BrightnessTracker { @VisibleForTesting static class Injector { public void registerSensorListener(Context context, - SensorEventListener sensorListener, Handler handler) { + SensorEventListener sensorListener, Sensor lightSensor, Handler handler) { SensorManager sensorManager = context.getSystemService(SensorManager.class); - Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); sensorManager.registerListener(sensorListener, lightSensor, SensorManager.SENSOR_DELAY_NORMAL, handler); } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index e4cda38e4ae5..77c1fc031598 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -795,7 +795,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) { // All properties that depend on the associated DisplayDevice and the DDC must be // updated here. - loadAmbientLightSensor(); loadBrightnessRampRates(); loadProximitySensor(); loadNitsRange(mContext.getResources()); @@ -925,6 +924,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } loadAmbientLightSensor(); + if (mBrightnessTracker != null) { + mBrightnessTracker.setLightSensor(mLightSensor); + } if (mAutomaticBrightnessController != null) { mAutomaticBrightnessController.stop(); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 211f8d6e3ec7..f3562d6cd87d 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -658,7 +658,14 @@ public class NotificationManagerService extends SystemService { return mBuffer.descendingIterator(); } - public StatusBarNotification[] getArray(int count, boolean includeSnoozed) { + public StatusBarNotification[] getArray(UserManager um, int count, boolean includeSnoozed) { + ArrayList<Integer> currentUsers = new ArrayList<>(); + currentUsers.add(UserHandle.USER_ALL); + Binder.withCleanCallingIdentity(() -> { + for (int user : um.getProfileIds(ActivityManager.getCurrentUser(), false)) { + currentUsers.add(user); + } + }); synchronized (mBufferLock) { if (count == 0) count = mBufferSize; List<StatusBarNotification> a = new ArrayList(); @@ -667,8 +674,10 @@ public class NotificationManagerService extends SystemService { while (iter.hasNext() && i < count) { Pair<StatusBarNotification, Integer> pair = iter.next(); if (pair.second != REASON_SNOOZED || includeSnoozed) { - i++; - a.add(pair.first); + if (currentUsers.contains(pair.first.getUserId())) { + i++; + a.add(pair.first); + } } } return a.toArray(new StatusBarNotification[a.size()]); @@ -4042,22 +4051,32 @@ public class NotificationManagerService extends SystemService { android.Manifest.permission.ACCESS_NOTIFICATIONS, "NotificationManagerService.getActiveNotifications"); - StatusBarNotification[] tmp = null; + ArrayList<StatusBarNotification> tmp = new ArrayList<>(); int uid = Binder.getCallingUid(); + ArrayList<Integer> currentUsers = new ArrayList<>(); + currentUsers.add(UserHandle.USER_ALL); + Binder.withCleanCallingIdentity(() -> { + for (int user : mUm.getProfileIds(ActivityManager.getCurrentUser(), false)) { + currentUsers.add(user); + } + }); + // noteOp will check to make sure the callingPkg matches the uid if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg, callingAttributionTag, null) == AppOpsManager.MODE_ALLOWED) { synchronized (mNotificationLock) { - tmp = new StatusBarNotification[mNotificationList.size()]; final int N = mNotificationList.size(); - for (int i=0; i<N; i++) { - tmp[i] = mNotificationList.get(i).getSbn(); + for (int i = 0; i < N; i++) { + final StatusBarNotification sbn = mNotificationList.get(i).getSbn(); + if (currentUsers.contains(sbn.getUserId())) { + tmp.add(sbn); + } } } } - return tmp; + return tmp.toArray(new StatusBarNotification[tmp.size()]); } /** @@ -4166,7 +4185,7 @@ public class NotificationManagerService extends SystemService { callingAttributionTag, null) == AppOpsManager.MODE_ALLOWED) { synchronized (mArchive) { - tmp = mArchive.getArray(count, includeSnoozed); + tmp = mArchive.getArray(mUm, count, includeSnoozed); } } return tmp; @@ -7695,7 +7714,9 @@ public class NotificationManagerService extends SystemService { int index = mToastQueue.indexOf(record); if (index >= 0) { - mToastQueue.remove(index); + ToastRecord toast = mToastQueue.remove(index); + mWindowManagerInternal.removeWindowToken( + toast.windowToken, true /* removeWindows */, toast.displayId); } record = (mToastQueue.size() > 0) ? mToastQueue.get(0) : null; } diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java index 4d1985590d7d..acbe04b8c519 100644 --- a/services/core/java/com/android/server/notification/ZenModeFiltering.java +++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java @@ -24,11 +24,14 @@ import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; import android.media.AudioAttributes; +import android.net.Uri; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings.Global; import android.service.notification.ZenModeConfig; import android.telecom.TelecomManager; +import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.Slog; @@ -36,6 +39,8 @@ import com.android.internal.messages.nano.SystemMessageProto; import com.android.internal.util.NotificationMessagingUtil; import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.util.Date; public class ZenModeFiltering { @@ -64,13 +69,22 @@ public class ZenModeFiltering { pw.print(prefix); pw.print("RepeatCallers.mThresholdMinutes="); pw.println(REPEAT_CALLERS.mThresholdMinutes); synchronized (REPEAT_CALLERS) { - if (!REPEAT_CALLERS.mCalls.isEmpty()) { - pw.print(prefix); pw.println("RepeatCallers.mCalls="); - for (int i = 0; i < REPEAT_CALLERS.mCalls.size(); i++) { + if (!REPEAT_CALLERS.mTelCalls.isEmpty()) { + pw.print(prefix); pw.println("RepeatCallers.mTelCalls="); + for (int i = 0; i < REPEAT_CALLERS.mTelCalls.size(); i++) { pw.print(prefix); pw.print(" "); - pw.print(REPEAT_CALLERS.mCalls.keyAt(i)); + pw.print(REPEAT_CALLERS.mTelCalls.keyAt(i)); pw.print(" at "); - pw.println(ts(REPEAT_CALLERS.mCalls.valueAt(i))); + pw.println(ts(REPEAT_CALLERS.mTelCalls.valueAt(i))); + } + } + if (!REPEAT_CALLERS.mOtherCalls.isEmpty()) { + pw.print(prefix); pw.println("RepeatCallers.mOtherCalls="); + for (int i = 0; i < REPEAT_CALLERS.mOtherCalls.size(); i++) { + pw.print(prefix); pw.print(" "); + pw.print(REPEAT_CALLERS.mOtherCalls.keyAt(i)); + pw.print(" at "); + pw.println(ts(REPEAT_CALLERS.mOtherCalls.valueAt(i))); } } } @@ -312,34 +326,39 @@ public class ZenModeFiltering { } private static class RepeatCallers { - // Person : time - private final ArrayMap<String, Long> mCalls = new ArrayMap<>(); + // We keep a separate map per uri scheme to do more generous number-matching + // handling on telephone numbers specifically. For other inputs, we + // simply match directly on the string. + private final ArrayMap<String, Long> mTelCalls = new ArrayMap<>(); + private final ArrayMap<String, Long> mOtherCalls = new ArrayMap<>(); private int mThresholdMinutes; private synchronized void recordCall(Context context, Bundle extras) { setThresholdMinutes(context); if (mThresholdMinutes <= 0 || extras == null) return; - final String peopleString = peopleString(extras); - if (peopleString == null) return; + final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras); + if (extraPeople == null || extraPeople.length == 0) return; final long now = System.currentTimeMillis(); - cleanUp(mCalls, now); - mCalls.put(peopleString, now); + cleanUp(mTelCalls, now); + cleanUp(mOtherCalls, now); + recordCallers(extraPeople, now); } private synchronized boolean isRepeat(Context context, Bundle extras) { setThresholdMinutes(context); if (mThresholdMinutes <= 0 || extras == null) return false; - final String peopleString = peopleString(extras); - if (peopleString == null) return false; + final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras); + if (extraPeople == null || extraPeople.length == 0) return false; final long now = System.currentTimeMillis(); - cleanUp(mCalls, now); - return mCalls.containsKey(peopleString); + cleanUp(mTelCalls, now); + cleanUp(mOtherCalls, now); + return checkCallers(context, extraPeople); } private synchronized void cleanUp(ArrayMap<String, Long> calls, long now) { final int N = calls.size(); for (int i = N - 1; i >= 0; i--) { - final long time = mCalls.valueAt(i); + final long time = calls.valueAt(i); if (time > now || (now - time) > mThresholdMinutes * 1000 * 60) { calls.removeAt(i); } @@ -353,21 +372,65 @@ public class ZenModeFiltering { } } - private static String peopleString(Bundle extras) { - final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras); - if (extraPeople == null || extraPeople.length == 0) return null; - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < extraPeople.length; i++) { - String extraPerson = extraPeople[i]; - if (extraPerson == null) continue; - extraPerson = extraPerson.trim(); - if (extraPerson.isEmpty()) continue; - if (sb.length() > 0) { - sb.append('|'); + private synchronized void recordCallers(String[] people, long now) { + for (int i = 0; i < people.length; i++) { + String person = people[i]; + if (person == null) continue; + final Uri uri = Uri.parse(person); + if ("tel".equals(uri.getScheme())) { + String tel = uri.getSchemeSpecificPart(); + // while ideally we should not need to do this, sometimes we have seen tel + // numbers given in a url-encoded format + try { + tel = URLDecoder.decode(tel, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // ignore, keep the original tel string + Slog.w(TAG, "unsupported encoding in tel: uri input"); + } + mTelCalls.put(tel, now); + } else { + // for non-tel calls, store the entire string, uri-component and all + mOtherCalls.put(person, now); } - sb.append(extraPerson); } - return sb.length() == 0 ? null : sb.toString(); + } + + private synchronized boolean checkCallers(Context context, String[] people) { + // get the default country code for checking telephone numbers + final String defaultCountryCode = + context.getSystemService(TelephonyManager.class).getNetworkCountryIso(); + for (int i = 0; i < people.length; i++) { + String person = people[i]; + if (person == null) continue; + final Uri uri = Uri.parse(person); + if ("tel".equals(uri.getScheme())) { + String number = uri.getSchemeSpecificPart(); + if (mTelCalls.containsKey(number)) { + // check directly via map first + return true; + } else { + // see if a number that matches via areSameNumber exists + String numberToCheck = number; + try { + numberToCheck = URLDecoder.decode(number, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // ignore, continue to use the original string + Slog.w(TAG, "unsupported encoding in tel: uri input"); + } + for (String prev : mTelCalls.keySet()) { + if (PhoneNumberUtils.areSamePhoneNumber( + numberToCheck, prev, defaultCountryCode)) { + return true; + } + } + } + } else { + if (mOtherCalls.containsKey(person)) { + return true; + } + } + } + return false; } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index d681f6985ea5..a46ae27ff8d9 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -10763,7 +10763,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public void resetNewUserDisclaimer() { + public void acknowledgeNewUserDisclaimer() { CallerIdentity callerIdentity = getCallerIdentity(); canManageUsers(callerIdentity); diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java index bdf94f3a2882..356600d84099 100644 --- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java @@ -33,6 +33,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ParceledListSlice; import android.database.ContentObserver; +import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.display.AmbientBrightnessDayStats; @@ -42,6 +43,7 @@ import android.hardware.display.ColorDisplayManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; +import android.hardware.input.InputSensorInfo; import android.os.BatteryManager; import android.os.Handler; import android.os.HandlerThread; @@ -63,6 +65,8 @@ import com.android.internal.R; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -84,8 +88,11 @@ public class BrightnessTrackerTest { private static final String DEFAULT_DISPLAY_ID = "123"; private static final float FLOAT_DELTA = 0.01f; + @Mock private InputSensorInfo mInputSensorInfoMock; + private BrightnessTracker mTracker; private TestInjector mInjector; + private Sensor mLightSensorFake; private static Object sHandlerLock = new Object(); private static Handler sHandler; @@ -108,9 +115,12 @@ public class BrightnessTrackerTest { @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); mInjector = new TestInjector(ensureHandler()); + mLightSensorFake = new Sensor(mInputSensorInfoMock); mTracker = new BrightnessTracker(InstrumentationRegistry.getContext(), mInjector); + mTracker.setLightSensor(mLightSensorFake); mDefaultNightModeColorTemperature = InstrumentationRegistry.getContext().getResources().getInteger( R.integer.config_nightDisplayColorTemperatureDefault); @@ -834,6 +844,47 @@ public class BrightnessTrackerTest { mTracker.stop(); } + @Test + public void testLightSensorChange() { + // verify the tracker started correctly and a listener registered + startTracker(mTracker); + assertNotNull(mInjector.mSensorListener); + assertEquals(mInjector.mLightSensor, mLightSensorFake); + + // Setting the sensor to null should stop the registered listener. + mTracker.setLightSensor(null); + mInjector.waitForHandler(); + assertNull(mInjector.mSensorListener); + assertNull(mInjector.mLightSensor); + + // Resetting sensor should start listener again + mTracker.setLightSensor(mLightSensorFake); + mInjector.waitForHandler(); + assertNotNull(mInjector.mSensorListener); + assertEquals(mInjector.mLightSensor, mLightSensorFake); + + Sensor secondSensor = new Sensor(mInputSensorInfoMock); + // Setting a different listener should keep things working + mTracker.setLightSensor(secondSensor); + mInjector.waitForHandler(); + assertNotNull(mInjector.mSensorListener); + assertEquals(mInjector.mLightSensor, secondSensor); + } + + @Test + public void testSetLightSensorDoesntStartListener() { + mTracker.setLightSensor(mLightSensorFake); + assertNull(mInjector.mSensorListener); + } + + @Test + public void testNullLightSensorWontRegister() { + mTracker.setLightSensor(null); + startTracker(mTracker); + assertNull(mInjector.mSensorListener); + assertNull(mInjector.mLightSensor); + } + private InputStream getInputStream(String data) { return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)); } @@ -924,6 +975,7 @@ public class BrightnessTrackerTest { private class TestInjector extends BrightnessTracker.Injector { SensorEventListener mSensorListener; + Sensor mLightSensor; BroadcastReceiver mBroadcastReceiver; DisplayManager.DisplayListener mDisplayListener; Map<String, Integer> mSecureIntSettings = new HashMap<>(); @@ -974,14 +1026,16 @@ public class BrightnessTrackerTest { @Override public void registerSensorListener(Context context, - SensorEventListener sensorListener, Handler handler) { + SensorEventListener sensorListener, Sensor lightSensor, Handler handler) { mSensorListener = sensorListener; + mLightSensor = lightSensor; } @Override public void unregisterSensorListener(Context context, SensorEventListener sensorListener) { mSensorListener = null; + mLightSensor = null; } @Override diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java index 1126e1ece452..4b6183dc9ffa 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java @@ -15,16 +15,22 @@ */ package com.android.server.notification; +import static android.os.UserHandle.USER_ALL; import static android.os.UserHandle.USER_CURRENT; +import static android.os.UserHandle.USER_NULL; import static android.os.UserHandle.USER_SYSTEM; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.when; import android.app.Notification; import android.os.UserHandle; +import android.os.UserManager; import android.service.notification.StatusBarNotification; import android.test.suitebuilder.annotation.SmallTest; @@ -35,6 +41,7 @@ import com.android.server.UiServiceTestCase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -51,6 +58,8 @@ public class ArchiveTest extends UiServiceTestCase { private static final int SIZE = 5; private NotificationManagerService.Archive mArchive; + @Mock + private UserManager mUm; @Before public void setUp() { @@ -59,6 +68,9 @@ public class ArchiveTest extends UiServiceTestCase { mArchive = new NotificationManagerService.Archive(SIZE); mArchive.updateHistoryEnabled(USER_SYSTEM, true); mArchive.updateHistoryEnabled(USER_CURRENT, true); + + when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn( + new int[] {USER_CURRENT, USER_SYSTEM}); } private StatusBarNotification getNotification(String pkg, int id, UserHandle user) { @@ -70,7 +82,6 @@ public class ArchiveTest extends UiServiceTestCase { pkg, pkg, id, null, 0, 0, n, user, null, System.currentTimeMillis()); } - @Test public void testRecordAndRead() { List<String> expected = new ArrayList<>(); @@ -81,7 +92,7 @@ public class ArchiveTest extends UiServiceTestCase { mArchive.record(sbn, REASON_CANCEL); } - List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true)); + List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true)); assertThat(actual).hasSize(expected.size()); for (StatusBarNotification sbn : actual) { assertThat(expected).contains(sbn.getKey()); @@ -89,6 +100,22 @@ public class ArchiveTest extends UiServiceTestCase { } @Test + public void testCrossUser() { + mArchive.record(getNotification("pkg", 1, UserHandle.of(USER_SYSTEM)), REASON_CANCEL); + mArchive.record(getNotification("pkg", 2, UserHandle.of(USER_CURRENT)), REASON_CANCEL); + mArchive.record(getNotification("pkg", 3, UserHandle.of(USER_ALL)), REASON_CANCEL); + mArchive.record(getNotification("pkg", 4, UserHandle.of(USER_NULL)), REASON_CANCEL); + + List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true)); + assertThat(actual).hasSize(3); + for (StatusBarNotification sbn : actual) { + if (sbn.getUserId() == USER_NULL) { + fail("leaked notification from wrong user"); + } + } + } + + @Test public void testRecordAndRead_overLimit() { List<String> expected = new ArrayList<>(); for (int i = 0; i < (SIZE * 2); i++) { @@ -99,7 +126,8 @@ public class ArchiveTest extends UiServiceTestCase { } } - List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray((SIZE * 2), true)); + List<StatusBarNotification> actual = Arrays.asList( + mArchive.getArray(mUm, (SIZE * 2), true)); assertThat(actual).hasSize(expected.size()); for (StatusBarNotification sbn : actual) { assertThat(expected).contains(sbn.getKey()); @@ -119,7 +147,7 @@ public class ArchiveTest extends UiServiceTestCase { } } - List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true)); + List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true)); assertThat(actual).hasSize(expected.size()); for (StatusBarNotification sbn : actual) { assertThat(expected).contains(sbn.getKey()); @@ -140,7 +168,7 @@ public class ArchiveTest extends UiServiceTestCase { } mArchive.updateHistoryEnabled(USER_CURRENT, false); - List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true)); + List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true)); assertThat(actual).hasSize(expected.size()); for (StatusBarNotification sbn : actual) { assertThat(expected).contains(sbn.getKey()); @@ -165,7 +193,7 @@ public class ArchiveTest extends UiServiceTestCase { } mArchive.removeChannelNotifications("pkg", USER_CURRENT, "test0"); mArchive.removeChannelNotifications("pkg", USER_CURRENT, "test" + (SIZE - 2)); - List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true)); + List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true)); assertThat(actual).hasSize(expected.size()); for (StatusBarNotification sbn : actual) { assertThat(expected).contains(sbn.getKey()); @@ -215,7 +243,7 @@ public class ArchiveTest extends UiServiceTestCase { fail("Concurrent modification exception"); } - List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true)); + List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true)); assertThat(actual).hasSize(expected.size()); for (StatusBarNotification sbn : actual) { assertThat(expected).contains(sbn.getKey()); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index e98d077836e0..b98401e76cc2 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -60,6 +60,7 @@ import static android.service.notification.NotificationListenerService.FLAG_FILT import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; +import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static com.google.common.truth.Truth.assertThat; @@ -475,6 +476,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG}); when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG}); mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); + when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0}); // write to a test file; the system file isn't readable from tests mFile = new File(mContext.getCacheDir(), "test.xml"); @@ -5572,6 +5574,39 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testRateLimitedToasts_windowsRemoved() throws Exception { + final String testPackage = "testPackageName"; + assertEquals(0, mService.mToastQueue.size()); + mService.isSystemUid = false; + setToastRateIsWithinQuota(false); // rate limit reached + setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); + setAppInForegroundForToasts(mUid, false); + + // package is not suspended + when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) + .thenReturn(false); + + Binder token = new Binder(); + INotificationManager nmService = (INotificationManager) mService.mService; + + nmService.enqueueTextToast(testPackage, token, "Text", 2000, 0, null); + + // window token was added when enqueued + ArgumentCaptor<Binder> binderCaptor = + ArgumentCaptor.forClass(Binder.class); + verify(mWindowManagerInternal).addWindowToken(binderCaptor.capture(), + eq(TYPE_TOAST), anyInt(), eq(null)); + + // but never shown + verify(mStatusBar, times(0)) + .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any()); + + // and removed when rate limited + verify(mWindowManagerInternal) + .removeWindowToken(eq(binderCaptor.getValue()), eq(true), anyInt()); + } + + @Test public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws Exception { final String testPackage = "testPackageName"; @@ -6970,8 +7005,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { waitForIdle(); // A notification exists for the given record - StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); - assertEquals(1, notifsBefore.length); + List<StatusBarNotification> notifsBefore = + mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList(); + assertEquals(1, notifsBefore.size()); reset(mPackageManager); @@ -8289,4 +8325,33 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001))); assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("test", 1002))); } + + @Test + public void testGetActiveNotification_filtersUsers() throws Exception { + when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10}); + + NotificationRecord nr0 = + generateNotificationRecord(mTestNotificationChannel, 0); + mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0", + nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId()); + + NotificationRecord nr10 = + generateNotificationRecord(mTestNotificationChannel, 10); + mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10", + nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId()); + + NotificationRecord nr11 = + generateNotificationRecord(mTestNotificationChannel, 11); + mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11", + nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId()); + waitForIdle(); + + StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); + assertEquals(2, notifs.length); + for (StatusBarNotification sbn : notifs) { + if (sbn.getUserId() == 11) { + fail("leaked data across users"); + } + } + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java index fb1508842c9d..0f18cc61a95a 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java @@ -17,7 +17,6 @@ package com.android.server.notification; import static android.app.Notification.CATEGORY_CALL; -import static android.app.Notification.CATEGORY_MESSAGE; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE; import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT; @@ -25,6 +24,7 @@ import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE; import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS; import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS; import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES; +import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS; import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; import static android.provider.Settings.Global.ZEN_MODE_ALARMS; @@ -43,8 +43,10 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager.Policy; import android.media.AudioAttributes; +import android.os.Bundle; import android.os.UserHandle; import android.service.notification.StatusBarNotification; +import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -68,10 +70,15 @@ public class ZenModeFilteringTest extends UiServiceTestCase { private NotificationMessagingUtil mMessagingUtil; private ZenModeFiltering mZenModeFiltering; + @Mock private TelephonyManager mTelephonyManager; + @Before public void setUp() { MockitoAnnotations.initMocks(this); mZenModeFiltering = new ZenModeFiltering(mContext, mMessagingUtil); + + // for repeat callers / matchesCallFilter + mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager); } private NotificationRecord getNotificationRecord() { @@ -95,6 +102,23 @@ public class ZenModeFilteringTest extends UiServiceTestCase { return r; } + private Bundle makeExtrasBundleWithPeople(String[] people) { + Bundle extras = new Bundle(); + extras.putObject(Notification.EXTRA_PEOPLE_LIST, people); + return extras; + } + + private NotificationRecord getNotificationRecordWithPeople(String[] people) { + // set up notification record + NotificationRecord r = mock(NotificationRecord.class); + StatusBarNotification sbn = mock(StatusBarNotification.class); + Notification notification = mock(Notification.class); + notification.extras = makeExtrasBundleWithPeople(people); + when(sbn.getNotification()).thenReturn(notification); + when(r.getSbn()).thenReturn(sbn); + return r; + } + @Test public void testIsMessage() { NotificationRecord r = getNotificationRecord(); @@ -309,4 +333,111 @@ public class ZenModeFilteringTest extends UiServiceTestCase { assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); } + + @Test + public void testMatchesCallFilter_repeatCallers_directMatch() { + // after calls given an email with an exact string match, make sure that + // matchesCallFilter returns the right thing + String[] mailSource = new String[]{"mailto:hello.world"}; + mZenModeFiltering.recordCall(getNotificationRecordWithPeople(mailSource)); + + // set up policy to only allow repeat callers + Policy policy = new Policy( + PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); + + // check whether matchesCallFilter returns the right thing + Bundle inputMatches = makeExtrasBundleWithPeople(new String[]{"mailto:hello.world"}); + Bundle inputWrong = makeExtrasBundleWithPeople(new String[]{"mailto:nope"}); + assertTrue(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + inputMatches, null, 0, 0)); + assertFalse(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + inputWrong, null, 0, 0)); + } + + @Test + public void testMatchesCallFilter_repeatCallers_telephoneVariants() { + // set up telephony manager behavior + when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); + + String[] telSource = new String[]{"tel:+1-617-555-1212"}; + mZenModeFiltering.recordCall(getNotificationRecordWithPeople(telSource)); + + // set up policy to only allow repeat callers + Policy policy = new Policy( + PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); + + // cases to test: + // - identical number + // - same number, different formatting + // - different number + // - garbage + Bundle identical = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"}); + Bundle same = makeExtrasBundleWithPeople(new String[]{"tel:16175551212"}); + Bundle different = makeExtrasBundleWithPeople(new String[]{"tel:123-456-7890"}); + Bundle garbage = makeExtrasBundleWithPeople(new String[]{"asdfghjkl;"}); + + assertTrue("identical numbers should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + identical, null, 0, 0)); + assertTrue("equivalent but non-identical numbers should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + same, null, 0, 0)); + assertFalse("non-equivalent numbers should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + different, null, 0, 0)); + assertFalse("non-tel strings should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + garbage, null, 0, 0)); + } + + @Test + public void testMatchesCallFilter_repeatCallers_urlEncodedTels() { + // this is not intended to be a supported case but is one that we have seen + // sometimes in the wild, so make sure we handle url-encoded telephone numbers correctly + // when somebody provides one. + + // set up telephony manager behavior + when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); + + String[] telSource = new String[]{"tel:%2B16175551212"}; + mZenModeFiltering.recordCall(getNotificationRecordWithPeople(telSource)); + + // set up policy to only allow repeat callers + Policy policy = new Policy( + PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); + + // test cases for various forms of the same phone number and different ones + Bundle same1 = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"}); + Bundle same2 = makeExtrasBundleWithPeople(new String[]{"tel:%2B1-617-555-1212"}); + Bundle same3 = makeExtrasBundleWithPeople(new String[]{"tel:6175551212"}); + Bundle different1 = makeExtrasBundleWithPeople(new String[]{"tel:%2B16175553434"}); + Bundle different2 = makeExtrasBundleWithPeople(new String[]{"tel:+16175553434"}); + + assertTrue("same number should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + same1, null, 0, 0)); + assertTrue("same number should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + same2, null, 0, 0)); + assertTrue("same number should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + same3, null, 0, 0)); + assertFalse("different number should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + different1, null, 0, 0)); + assertFalse("different number should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + different2, null, 0, 0)); + } } |