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

Commit c50403c6 authored by Christine Franks's avatar Christine Franks
Browse files

Prevent apps from displaying over Settings

Specifically, the DrawOverlayDetails fragment only.

Bug: 36070413
Test: make RunSettingsRoboTests -j100
Change-Id: I0069f0cacf8c963c8c6878dc89a32b205983a568
parent 418e5bff
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateOverlayBridge.OverlayState;
import com.android.settings.core.TouchOverlayManager;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.applications.ApplicationsState.AppEntry;

@@ -61,6 +62,8 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
    private Intent mSettingsIntent;
    private OverlayState mOverlayState;

    private TouchOverlayManager mTouchOverlayManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
@@ -68,6 +71,7 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
        Context context = getActivity();
        mOverlayBridge = new AppStateOverlayBridge(context, mState, null);
        mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        mTouchOverlayManager = new TouchOverlayManager(context);

        // find preferences
        addPreferencesFromResource(R.xml.app_ops_permissions_details);
@@ -89,6 +93,20 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
                .setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
    }

    @Override
    public void onStart() {
        super.onStart();

        mTouchOverlayManager.setOverlayAllowed(false);
    }

    @Override
    public void onStop() {
        super.onStop();

        mTouchOverlayManager.setOverlayAllowed(true);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
+40 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.settings.core;

import android.app.AppOpsManager;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;

public class TouchOverlayManager {

    private final Context mContext;
    private final IBinder mToken = new Binder();

    public TouchOverlayManager(Context context) {
        mContext = context;
    }

    public void setOverlayAllowed(boolean allowed) {
        final AppOpsManager aom = mContext.getSystemService(AppOpsManager.class);
        if (aom != null) {
            aom.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, !allowed, mToken);
            aom.setUserRestriction(AppOpsManager.OP_TOAST_WINDOW, !allowed, mToken);
        }
    }
}
+23 −2
Original line number Diff line number Diff line
@@ -19,10 +19,11 @@ package com.android.settings.applications;
import android.content.Context;

import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.telephony.SmsUsageMonitor;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.core.TouchOverlayManager;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowPreferenceFragment;

import org.junit.Before;
import org.junit.Test;
@@ -32,6 +33,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
@@ -47,17 +49,22 @@ public class DrawOverlayDetailsTest {
    private FakeFeatureFactory mFeatureFactory;
    private DrawOverlayDetails mFragment;

    @Mock
    private TouchOverlayManager mTouchOverlayManager;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        FakeFeatureFactory.setupForTest(mContext);
        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);

        mFragment = new DrawOverlayDetails();
        mFragment.onAttach(ShadowApplication.getInstance().getApplicationContext());
        ReflectionHelpers.setField(mFragment, "mTouchOverlayManager", mTouchOverlayManager);
    }

    @Test
    public void logSpecialPermissionChange() {
        mFragment.onAttach(ShadowApplication.getInstance().getApplicationContext());
        mFragment.logSpecialPermissionChange(true, "app");
        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_APPDRAW_ALLOW), eq("app"));
@@ -66,4 +73,18 @@ public class DrawOverlayDetailsTest {
        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_APPDRAW_DENY), eq("app"));
    }

    @Test
    @Config(shadows = ShadowPreferenceFragment.class)
    public void onStart_disableOverlay() {
        mFragment.onStart();
        verify(mTouchOverlayManager).setOverlayAllowed(false);
    }

    @Test
    @Config(shadows = ShadowPreferenceFragment.class)
    public void onStop_enableOverlay() {
        mFragment.onStop();
        verify(mTouchOverlayManager).setOverlayAllowed(true);
    }
}
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.settings.testutils.shadow;

import android.support.v14.preference.PreferenceFragment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;

@Implements(PreferenceFragment.class)
public class ShadowPreferenceFragment {

    @Implementation
    public void onStart() {
        // No-op.
    }

    @Implementation
    public void onStop() {
        // No-op.
    }
}