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

Commit 9cb867d6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Use new no overlay flag instead app ops" into oc-mr1-dev

parents 47dd955f e53d1cae
Loading
Loading
Loading
Loading
+10 −22
Original line number Diff line number Diff line
@@ -29,12 +29,13 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.util.Log;

import android.view.Window;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
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;

@@ -60,8 +61,6 @@ 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);
@@ -69,7 +68,6 @@ 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);
@@ -92,17 +90,17 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
    }

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

        mTouchOverlayManager.setOverlayAllowed(false);
    public void onResume() {
        super.onResume();
        getActivity().getWindow().addFlags(
                WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
    }

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

        mTouchOverlayManager.setOverlayAllowed(true);
    public void onPause() {
        getActivity().getWindow().clearFlags(
                WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
        super.onPause();
    }

    @Override
@@ -153,16 +151,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
                .getMetricsFeatureProvider().action(getContext(), logCategory, packageName);
    }

    private boolean canDrawOverlay(String pkgName) {
        int result = mAppOpsManager.noteOpNoThrow(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
                mPackageInfo.applicationInfo.uid, pkgName);
        if (result == AppOpsManager.MODE_ALLOWED) {
            return true;
        }

        return false;
    }

    @Override
    protected boolean refreshUi() {
        mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName,
+0 −40
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);
        }
    }
}
+15 −17
Original line number Diff line number Diff line
@@ -35,15 +35,13 @@ import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.SettingsStringUtil;
import android.util.Slog;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;

import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.settings.R;
import com.android.settings.core.TouchOverlayManager;

/** @hide */
public class NotificationAccessConfirmationActivity extends Activity
@@ -54,14 +52,12 @@ public class NotificationAccessConfirmationActivity extends Activity

    private int mUserId;
    private ComponentName mComponentName;
    private TouchOverlayManager mTouchOverlayManager;
    private NotificationManager mNm;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mTouchOverlayManager = new TouchOverlayManager(this);
        mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        mComponentName = getIntent().getParcelableExtra(EXTRA_COMPONENT_NAME);
@@ -84,6 +80,20 @@ public class NotificationAccessConfirmationActivity extends Activity
                .installContent(p);
    }

    @Override
    public void onResume() {
        super.onResume();
        getWindow().addFlags(
                WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
    }

    @Override
    public void onPause() {
        getWindow().clearFlags(
                WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
        super.onPause();
    }

    private void onAllow() {
        String requiredPermission = Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
        try {
@@ -121,16 +131,4 @@ public class NotificationAccessConfirmationActivity extends Activity
            finish();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        mTouchOverlayManager.setOverlayAllowed(false);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mTouchOverlayManager.setOverlayAllowed(true);
    }
}
+31 −23
Original line number Diff line number Diff line
@@ -19,52 +19,59 @@ package com.android.settings.applications;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.nullable;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;

import android.app.Activity;
import android.content.Context;

import android.view.Window;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.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 com.android.settings.testutils.shadow.ShadowAppInfoBase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class DrawOverlayDetailsTest {

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private Context mContext;
    private Activity mActivity;

    @Mock
    private Window mWindow;

    private FakeFeatureFactory mFeatureFactory;
    private DrawOverlayDetails mFragment;

    @Mock
    private TouchOverlayManager mTouchOverlayManager;
    @Spy
    private DrawOverlayDetails mFragment;

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

        mFragment = new DrawOverlayDetails();
        ReflectionHelpers.setField(mFragment, "mTouchOverlayManager", mTouchOverlayManager);
        FakeFeatureFactory.setupForTest(mActivity);
        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mActivity);
    }

    @Test
    public void logSpecialPermissionChange() {
        mFragment.onAttach(ShadowApplication.getInstance().getApplicationContext());
        when(mFragment.getContext()).thenReturn(
                ShadowApplication.getInstance().getApplicationContext());

        mFragment.logSpecialPermissionChange(true, "app");
        verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_APPDRAW_ALLOW), eq("app"));
@@ -75,16 +82,17 @@ public class DrawOverlayDetailsTest {
    }

    @Test
    @Config(shadows = ShadowPreferenceFragment.class)
    public void onStart_disableOverlay() {
        mFragment.onStart();
        verify(mTouchOverlayManager).setOverlayAllowed(false);
    }
    @Config(shadows = {ShadowAppInfoBase.class})
    public void hideNonSystemOverlaysWhenResumed() {
        when(mFragment.getActivity()).thenReturn(mActivity);
        when(mActivity.getWindow()).thenReturn(mWindow);

    @Test
    @Config(shadows = ShadowPreferenceFragment.class)
    public void onStop_enableOverlay() {
        mFragment.onStop();
        verify(mTouchOverlayManager).setOverlayAllowed(true);
        mFragment.onResume();
        mFragment.onPause();

        InOrder inOrder = Mockito.inOrder(mWindow);
        inOrder.verify(mWindow).addFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
        inOrder.verify(mWindow).clearFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
        inOrder.verifyNoMoreInteractions();
    }
}
+5 −5
Original line number Diff line number Diff line
@@ -16,20 +16,20 @@

package com.android.settings.testutils.shadow;

import android.support.v14.preference.PreferenceFragment;
import com.android.settings.applications.AppInfoBase;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;

@Implements(PreferenceFragment.class)
public class ShadowPreferenceFragment {
@Implements(AppInfoBase.class)
public class ShadowAppInfoBase {

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

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