Loading src/com/android/settings/applications/DrawOverlayDetails.java +18 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading @@ -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(); Loading src/com/android/settings/core/TouchOverlayManager.java 0 → 100644 +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); } } } tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java +23 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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")); Loading @@ -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); } } tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java 0 → 100644 +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. } } Loading
src/com/android/settings/applications/DrawOverlayDetails.java +18 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading @@ -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(); Loading
src/com/android/settings/core/TouchOverlayManager.java 0 → 100644 +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); } } }
tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java +23 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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")); Loading @@ -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); } }
tests/robotests/src/com/android/settings/testutils/shadow/ShadowPreferenceFragment.java 0 → 100644 +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. } }