Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe86a2a5 authored by Raff Tsai's avatar Raff Tsai
Browse files

Do not allow draw on top for App notification settings

Fixes: 119115683
Test: manual
Change-Id: Ib7b878a23b4a99171c58b5de992fb87feca8a28a
parent f514f1ee
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -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();
@@ -118,6 +123,15 @@ public class AppNotificationSettings extends NotificationSettingsBase {
        updatePreferenceStates();
    }

    @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;
+93 −0
Original line number Diff line number Diff line
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<WindowManager.LayoutParams> 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.
        }
    }
}