From e53d1caedc876351ee68dccd48c3187686b5ae6e Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Mon, 2 Oct 2017 18:58:08 -0700 Subject: [PATCH] Use new no overlay flag instead app ops Test: updated DrawOverlayDetailsTest passes bug:66936547 Change-Id: I7c17c95a2b44fd2ffd593a6eb03a16be034e9192 --- .../applications/DrawOverlayDetails.java | 32 ++++------- .../settings/core/TouchOverlayManager.java | 40 ------------- ...otificationAccessConfirmationActivity.java | 32 +++++------ .../applications/DrawOverlayDetailsTest.java | 56 +++++++++++-------- ...ceFragment.java => ShadowAppInfoBase.java} | 10 ++-- 5 files changed, 62 insertions(+), 108 deletions(-) delete mode 100644 src/com/android/settings/core/TouchOverlayManager.java rename tests/robotests/src/com/android/settings/testutils/shadow/{ShadowPreferenceFragment.java => ShadowAppInfoBase.java} (81%) diff --git a/src/com/android/settings/applications/DrawOverlayDetails.java b/src/com/android/settings/applications/DrawOverlayDetails.java index c6f3cc0c1e6..78f1c082042 100644 --- a/src/com/android/settings/applications/DrawOverlayDetails.java +++ b/src/com/android/settings/applications/DrawOverlayDetails.java @@ -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, diff --git a/src/com/android/settings/core/TouchOverlayManager.java b/src/com/android/settings/core/TouchOverlayManager.java deleted file mode 100644 index f69d1bfbb6c..00000000000 --- a/src/com/android/settings/core/TouchOverlayManager.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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); - } - } -} diff --git a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java index 6a13282285d..f9eabb94994 100644 --- a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java +++ b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java @@ -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); - } } diff --git a/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java b/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java index 6122576bb3e..5d20a4c9cc3 100644 --- a/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java @@ -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 FakeFeatureFactory mFeatureFactory; - private DrawOverlayDetails mFragment; + private Activity mActivity; @Mock - private TouchOverlayManager mTouchOverlayManager; + private Window mWindow; + + private FakeFeatureFactory mFeatureFactory; + + @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(); } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAppInfoBase.java similarity index 81% rename from tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java rename to tests/robotests/src/com/android/settings/testutils/shadow/ShadowAppInfoBase.java index cfd0ce931d6..12173c8f1de 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAppInfoBase.java @@ -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. } }