Loading src/com/android/settings/applications/appinfo/DrawOverlayDetails.java +5 −38 Original line number Diff line number Diff line Loading @@ -15,22 +15,13 @@ */ package com.android.settings.applications.appinfo; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; Loading @@ -55,16 +46,11 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; private static final String LOG_TAG = "DrawOverlayDetails"; private static final int[] APP_OPS_OP_CODE = { AppOpsManager.OP_SYSTEM_ALERT_WINDOW }; // Use a bridge to get the overlay details but don't initialize it to connect with all state. // TODO: Break out this functionality into its own class. private AppStateOverlayBridge mOverlayBridge; private AppOpsManager mAppOpsManager; private SwitchPreference mSwitchPref; private Intent mSettingsIntent; private OverlayState mOverlayState; @Override Loading @@ -82,13 +68,10 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc // find preferences addPreferencesFromResource(R.xml.draw_overlay_permissions_details); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); mSwitchPref = findPreference(KEY_APP_OPS_SETTINGS_SWITCH); // install event listeners mSwitchPref.setOnPreferenceChangeListener(this); mSettingsIntent = new Intent(Intent.ACTION_MAIN) .setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); } // Override here so we don't have an empty screen Loading @@ -103,21 +86,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onResume() { super.onResume(); getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); } @Override public void onPause() { super.onPause(); Window window = getActivity().getWindow(); WindowManager.LayoutParams attrs = window.getAttributes(); attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; window.setAttributes(attrs); } @Override public void onDestroy() { super.onDestroy(); Loading Loading @@ -164,7 +132,9 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc @Override protected boolean refreshUi() { if (mPackageInfo == null) return true; if (mPackageInfo == null) { return true; } mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName, mPackageInfo.applicationInfo.uid); Loading @@ -174,9 +144,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc // you cannot ask a user to grant you a permission you did not have! mSwitchPref.setEnabled(mOverlayState.permissionDeclared && mOverlayState.controlEnabled); ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent, PackageManager.GET_META_DATA, mUserId); return true; } Loading src/com/android/settings/core/HideNonSystemOverlayMixin.java 0 → 100644 +64 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static androidx.lifecycle.Lifecycle.Event.ON_START; import static androidx.lifecycle.Lifecycle.Event.ON_STOP; import android.app.Activity; import android.view.Window; import android.view.WindowManager; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; /** * A mixin that adds window flag to prevent non-system overlays showing on top of Settings * activities. */ public class HideNonSystemOverlayMixin implements LifecycleObserver { private final Activity mActivity; public HideNonSystemOverlayMixin(Activity activity) { mActivity = activity; } @OnLifecycleEvent(ON_START) public void onStart() { if (mActivity == null) { return; } mActivity.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); android.util.EventLog.writeEvent(0x534e4554, "120484087", -1, ""); } @OnLifecycleEvent(ON_STOP) public void onStop() { if (mActivity == null) { return; } final Window window = mActivity.getWindow(); final WindowManager.LayoutParams attrs = window.getAttributes(); attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; window.setAttributes(attrs); } } src/com/android/settings/core/SettingsBaseActivity.java +1 −2 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.widget.Toolbar; import androidx.fragment.app.FragmentActivity; Loading @@ -59,8 +58,8 @@ public class SettingsBaseActivity extends FragmentActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); final long startTime = System.currentTimeMillis(); getLifecycle().addObserver(new HideNonSystemOverlayMixin(this)); final TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme); if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) { Loading src/com/android/settings/notification/AppNotificationSettings.java +0 −15 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.settings.notification; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; import android.app.settings.SettingsEnums; Loading @@ -26,8 +24,6 @@ import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.Window; import android.view.WindowManager; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; Loading Loading @@ -88,8 +84,6 @@ public class AppNotificationSettings extends NotificationSettingsBase { public void onResume() { super.onResume(); getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) { Log.w(TAG, "Missing package or uid or packageinfo"); finish(); Loading Loading @@ -123,15 +117,6 @@ public class AppNotificationSettings extends NotificationSettingsBase { updatePreferenceStates(); } @Override public void onPause() { super.onPause(); final Window window = getActivity().getWindow(); final WindowManager.LayoutParams attrs = window.getAttributes(); attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; window.setAttributes(attrs); } @Override protected String getLogTag() { return TAG; Loading tests/robotests/src/com/android/settings/core/HideNonSystemOverlayMixinTest.java 0 → 100644 +78 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static com.google.common.truth.Truth.assertThat; import android.os.Bundle; import android.view.WindowManager; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.android.settings.R; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.android.controller.ActivityController; @RunWith(RobolectricTestRunner.class) public class HideNonSystemOverlayMixinTest { private ActivityController<TestActivity> mActivityController; @Before public void setUp() { RuntimeEnvironment.application.setTheme(R.style.Theme_AppCompat); mActivityController = Robolectric.buildActivity(TestActivity.class); } @Test public void startActivity_shouldHideNonSystemOverlay() { mActivityController.setup(); TestActivity activity = mActivityController.get(); // Activity start: HIDE_NON_SYSTEM_OVERLAY should be set. final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); assertThat(attrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) .isNotEqualTo(0); } @Test public void stopActivity_shouldUnhideNonSystemOverlay() { mActivityController.setup().stop(); TestActivity activity = mActivityController.get(); final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); assertThat(attrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) .isEqualTo(0); } public static class TestActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getLifecycle().addObserver(new HideNonSystemOverlayMixin(this)); } } } Loading
src/com/android/settings/applications/appinfo/DrawOverlayDetails.java +5 −38 Original line number Diff line number Diff line Loading @@ -15,22 +15,13 @@ */ package com.android.settings.applications.appinfo; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; Loading @@ -55,16 +46,11 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; private static final String LOG_TAG = "DrawOverlayDetails"; private static final int[] APP_OPS_OP_CODE = { AppOpsManager.OP_SYSTEM_ALERT_WINDOW }; // Use a bridge to get the overlay details but don't initialize it to connect with all state. // TODO: Break out this functionality into its own class. private AppStateOverlayBridge mOverlayBridge; private AppOpsManager mAppOpsManager; private SwitchPreference mSwitchPref; private Intent mSettingsIntent; private OverlayState mOverlayState; @Override Loading @@ -82,13 +68,10 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc // find preferences addPreferencesFromResource(R.xml.draw_overlay_permissions_details); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); mSwitchPref = findPreference(KEY_APP_OPS_SETTINGS_SWITCH); // install event listeners mSwitchPref.setOnPreferenceChangeListener(this); mSettingsIntent = new Intent(Intent.ACTION_MAIN) .setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); } // Override here so we don't have an empty screen Loading @@ -103,21 +86,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onResume() { super.onResume(); getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); } @Override public void onPause() { super.onPause(); Window window = getActivity().getWindow(); WindowManager.LayoutParams attrs = window.getAttributes(); attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; window.setAttributes(attrs); } @Override public void onDestroy() { super.onDestroy(); Loading Loading @@ -164,7 +132,9 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc @Override protected boolean refreshUi() { if (mPackageInfo == null) return true; if (mPackageInfo == null) { return true; } mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName, mPackageInfo.applicationInfo.uid); Loading @@ -174,9 +144,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc // you cannot ask a user to grant you a permission you did not have! mSwitchPref.setEnabled(mOverlayState.permissionDeclared && mOverlayState.controlEnabled); ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent, PackageManager.GET_META_DATA, mUserId); return true; } Loading
src/com/android/settings/core/HideNonSystemOverlayMixin.java 0 → 100644 +64 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static androidx.lifecycle.Lifecycle.Event.ON_START; import static androidx.lifecycle.Lifecycle.Event.ON_STOP; import android.app.Activity; import android.view.Window; import android.view.WindowManager; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; /** * A mixin that adds window flag to prevent non-system overlays showing on top of Settings * activities. */ public class HideNonSystemOverlayMixin implements LifecycleObserver { private final Activity mActivity; public HideNonSystemOverlayMixin(Activity activity) { mActivity = activity; } @OnLifecycleEvent(ON_START) public void onStart() { if (mActivity == null) { return; } mActivity.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); android.util.EventLog.writeEvent(0x534e4554, "120484087", -1, ""); } @OnLifecycleEvent(ON_STOP) public void onStop() { if (mActivity == null) { return; } final Window window = mActivity.getWindow(); final WindowManager.LayoutParams attrs = window.getAttributes(); attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; window.setAttributes(attrs); } }
src/com/android/settings/core/SettingsBaseActivity.java +1 −2 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.widget.Toolbar; import androidx.fragment.app.FragmentActivity; Loading @@ -59,8 +58,8 @@ public class SettingsBaseActivity extends FragmentActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); final long startTime = System.currentTimeMillis(); getLifecycle().addObserver(new HideNonSystemOverlayMixin(this)); final TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme); if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) { Loading
src/com/android/settings/notification/AppNotificationSettings.java +0 −15 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.settings.notification; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; import android.app.settings.SettingsEnums; Loading @@ -26,8 +24,6 @@ import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.Window; import android.view.WindowManager; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; Loading Loading @@ -88,8 +84,6 @@ public class AppNotificationSettings extends NotificationSettingsBase { public void onResume() { super.onResume(); getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) { Log.w(TAG, "Missing package or uid or packageinfo"); finish(); Loading Loading @@ -123,15 +117,6 @@ public class AppNotificationSettings extends NotificationSettingsBase { updatePreferenceStates(); } @Override public void onPause() { super.onPause(); final Window window = getActivity().getWindow(); final WindowManager.LayoutParams attrs = window.getAttributes(); attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; window.setAttributes(attrs); } @Override protected String getLogTag() { return TAG; Loading
tests/robotests/src/com/android/settings/core/HideNonSystemOverlayMixinTest.java 0 → 100644 +78 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static com.google.common.truth.Truth.assertThat; import android.os.Bundle; import android.view.WindowManager; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.android.settings.R; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.android.controller.ActivityController; @RunWith(RobolectricTestRunner.class) public class HideNonSystemOverlayMixinTest { private ActivityController<TestActivity> mActivityController; @Before public void setUp() { RuntimeEnvironment.application.setTheme(R.style.Theme_AppCompat); mActivityController = Robolectric.buildActivity(TestActivity.class); } @Test public void startActivity_shouldHideNonSystemOverlay() { mActivityController.setup(); TestActivity activity = mActivityController.get(); // Activity start: HIDE_NON_SYSTEM_OVERLAY should be set. final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); assertThat(attrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) .isNotEqualTo(0); } @Test public void stopActivity_shouldUnhideNonSystemOverlay() { mActivityController.setup().stop(); TestActivity activity = mActivityController.get(); final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); assertThat(attrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) .isEqualTo(0); } public static class TestActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getLifecycle().addObserver(new HideNonSystemOverlayMixin(this)); } } }