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

Commit 93c69097 authored by Fan Zhang's avatar Fan Zhang Committed by Android (Google) Code Review
Browse files

Merge "Disable draw overlay for most of Settings."

parents 7099f1ce 9d983441
Loading
Loading
Loading
Loading
+5 −38
Original line number Diff line number Diff line
@@ -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;
@@ -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
@@ -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
@@ -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();
@@ -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);
@@ -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;
    }

+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);
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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)) {
+0 −15
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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();
@@ -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;
+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));
        }
    }
}