Loading src/com/android/settings/applications/DrawOverlayDetails.java +10 −22 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading @@ -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 Loading Loading @@ -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, Loading src/com/android/settings/core/TouchOverlayManager.javadeleted 100644 → 0 +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); } } } src/com/android/settings/notification/NotificationAccessConfirmationActivity.java +15 −17 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); Loading @@ -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 { Loading Loading @@ -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); } } tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java +31 −23 Original line number Diff line number Diff line Loading @@ -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")); Loading @@ -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(); } } tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java→tests/robotests/src/com/android/settings/testutils/shadow/ShadowAppInfoBase.java +5 −5 Original line number Diff line number Diff line Loading @@ -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. } } Loading
src/com/android/settings/applications/DrawOverlayDetails.java +10 −22 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading @@ -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 Loading Loading @@ -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, Loading
src/com/android/settings/core/TouchOverlayManager.javadeleted 100644 → 0 +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); } } }
src/com/android/settings/notification/NotificationAccessConfirmationActivity.java +15 −17 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); Loading @@ -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 { Loading Loading @@ -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); } }
tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java +31 −23 Original line number Diff line number Diff line Loading @@ -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")); Loading @@ -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(); } }
tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java→tests/robotests/src/com/android/settings/testutils/shadow/ShadowAppInfoBase.java +5 −5 Original line number Diff line number Diff line Loading @@ -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. } }