From fe86a2a51f0b8e01e5f595bd60edc594eef58aba Mon Sep 17 00:00:00 2001 From: Raff Tsai Date: Fri, 8 Mar 2019 16:19:30 +0800 Subject: [PATCH] Do not allow draw on top for App notification settings Fixes: 119115683 Test: manual Change-Id: Ib7b878a23b4a99171c58b5de992fb87feca8a28a --- .../notification/AppNotificationSettings.java | 16 +++- .../notification/AppNotificationSettingsTest.java | 93 ++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 tests/robotests/src/com/android/settings/notification/AppNotificationSettingsTest.java diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java index 5553dd7bf3..9f5ece24a5 100644 --- a/src/com/android/settings/notification/AppNotificationSettings.java +++ b/src/com/android/settings/notification/AppNotificationSettings.java @@ -16,6 +16,8 @@ package com.android.settings.notification; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + import android.app.NotificationChannel; import android.app.NotificationChannelGroup; import android.app.settings.SettingsEnums; @@ -24,6 +26,8 @@ import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; +import android.view.Window; +import android.view.WindowManager; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; @@ -33,7 +37,6 @@ import androidx.preference.SwitchPreference; import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; -import com.android.settings.widget.MasterCheckBoxPreference; import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.core.AbstractPreferenceController; @@ -85,6 +88,8 @@ public class AppNotificationSettings extends NotificationSettingsBase { public void onResume() { super.onResume(); + getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) { Log.w(TAG, "Missing package or uid or packageinfo"); finish(); @@ -119,6 +124,15 @@ public class AppNotificationSettings extends NotificationSettingsBase { } @Override + public void onPause() { + super.onPause(); + final Window window = getActivity().getWindow(); + final WindowManager.LayoutParams attrs = window.getAttributes(); + attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + window.setAttributes(attrs); + } + + @Override protected String getLogTag() { return TAG; } diff --git a/tests/robotests/src/com/android/settings/notification/AppNotificationSettingsTest.java b/tests/robotests/src/com/android/settings/notification/AppNotificationSettingsTest.java new file mode 100644 index 0000000000..9555a56e1b --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/AppNotificationSettingsTest.java @@ -0,0 +1,93 @@ +package com.android.settings.notification; + +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.view.Window; +import android.view.WindowManager; + +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@RunWith(RobolectricTestRunner.class) +public class AppNotificationSettingsTest { + + private WindowManager.LayoutParams mLayoutParams; + private AppNotificationSettings mFragment; + private FragmentActivity mActivity; + @Mock + private Window mWindow; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mLayoutParams = new WindowManager.LayoutParams(); + mActivity = spy(Robolectric.setupActivity(FragmentActivity.class)); + mFragment = spy(new AppNotificationSettings()); + when(mFragment.getActivity()).thenReturn(mActivity); + when(mFragment.getFragmentManager()).thenReturn(mock(FragmentManager.class)); + when(mActivity.getWindow()).thenReturn(mWindow); + when(mWindow.getAttributes()).thenReturn(mLayoutParams); + } + + @Test + @Config(shadows = {ShadowNotificationSettingsBase.class}) + public void onResume_shouldHideSystemOverlay() { + mFragment.onResume(); + + verify(mWindow).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + } + + @Test + @Config(shadows = {ShadowNotificationSettingsBase.class}) + public void onPause_shouldRemoveHideSystemOverlay() { + mFragment.onResume(); + + verify(mWindow).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + + mFragment.onPause(); + + // There's no Window.clearPrivateFlags() method, so the Window.attributes are updated. + ArgumentCaptor paramCaptor = ArgumentCaptor.forClass( + WindowManager.LayoutParams.class); + verify(mWindow).setAttributes(paramCaptor.capture()); + assertEquals(0, + paramCaptor.getValue().privateFlags + & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + } + + @Implements(NotificationSettingsBase.class) + public static class ShadowNotificationSettingsBase { + + protected void __constructor__() { + // Do nothing + } + + @Implementation + protected void onResume() { + // No-op. + } + + @Implementation + protected void onPause() { + // No-op. + } + } +} -- 2.11.0