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

Commit a4ffa0ac authored by Bryce Lee's avatar Bryce Lee
Browse files

Exclude CommunalSurfaceView tap region from keyguard.

This changelist excludes the fullscreen tap region
(minus header and footer margin) when communal is
visible. This allows touches to pass through the
notification shade window to the CommunalSurfaceView
underneath.

Note that this currently has no effect on the
CommunalSurfaceView as it is on top of the z-order.
However, subsequent changes will move the
CommunalSurfaceView into the correct z-order.

Test: CommunalSurfaceViewControllerTest#testTapExclusion
Bug: 197026983
Change-Id: Ib80bdbb788e20756c18646833c23f844273af82c
parent 0320d8c7
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardVisibilityHelper;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -121,6 +122,11 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>

                    setState(STATE_DOZING, isDozing);
                }

                @Override
                public void onStateChanged(int newState) {
                    updateCommunalViewOccluded();
                }
            };

    @Inject
@@ -195,6 +201,8 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>
        if (existingState != mState) {
            showSource();
        }

        updateCommunalViewOccluded();
    }

    private String describeState(@State int stateFlag) {
@@ -308,7 +316,12 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>
    }

    private void updateCommunalViewOccluded() {
        final boolean bouncerShowing = (mState & STATE_BOUNCER_SHOWING) == STATE_BOUNCER_SHOWING;
        final int statusBarState = mStatusBarStateController.getState();
        final boolean shadeExpanded = statusBarState == StatusBarState.SHADE
                || statusBarState == StatusBarState.SHADE_LOCKED;

        mCommunalStateController.setCommunalViewOccluded(
                mQsExpansion > 0.0f || mShadeExpansion > 0.0f);
                bouncerShowing || shadeExpanded || mQsExpansion > 0.0f || mShadeExpansion > 0.0f);
    }
}
+23 −7
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.communal.service;

import android.content.Context;
import android.content.res.Resources;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -30,6 +31,7 @@ import com.android.systemui.communal.CommunalStateController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.communal.ICommunalSource;
import com.android.systemui.shared.communal.ICommunalSurfaceCallback;
import com.android.systemui.statusbar.NotificationShadeWindowController;

import com.google.android.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture;
@@ -47,23 +49,32 @@ import javax.inject.Inject;
 */
public class CommunalSourceImpl implements CommunalSource {
    private static final String TAG = "CommunalSourceImpl";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private final ICommunalSource mSourceProxy;
    private final Resources mResources;
    private final Executor mMainExecutor;
    private final NotificationShadeWindowController mNotificationShadeWindowController;
    private final CommunalStateController mCommunalStateController;

    static class Factory {
        private final Executor mExecutor;
        private final Resources mResources;
        private final CommunalStateController mCommunalStateController;
        private final NotificationShadeWindowController mNotificationShadeWindowController;

        @Inject
        Factory(@Main Executor executor, CommunalStateController communalStateController) {
        Factory(@Main Executor executor, @Main Resources resources,
                NotificationShadeWindowController notificationShadeWindowController,
                CommunalStateController communalStateController) {
            mExecutor = executor;
            mResources = resources;
            mNotificationShadeWindowController = notificationShadeWindowController;
            mCommunalStateController = communalStateController;
        }

        public CommunalSource create(ICommunalSource source) {
            return new CommunalSourceImpl(mExecutor, mCommunalStateController, source);
            return new CommunalSourceImpl(mExecutor, mResources, mCommunalStateController,
                    mNotificationShadeWindowController, source);
        }
    }

@@ -75,10 +86,14 @@ public class CommunalSourceImpl implements CommunalSource {
    // A list of {@link Callback} that have registered to receive updates.
    private final ArrayList<WeakReference<Callback>> mCallbacks = Lists.newArrayList();

    public CommunalSourceImpl(Executor mainExecutor,
            CommunalStateController communalStateController, ICommunalSource sourceProxy) {
    public CommunalSourceImpl(Executor mainExecutor, Resources resources,
            CommunalStateController communalStateController,
            NotificationShadeWindowController notificationShadeWindowController,
            ICommunalSource sourceProxy) {
        mMainExecutor = mainExecutor;
        mCommunalStateController = communalStateController;
        mNotificationShadeWindowController = notificationShadeWindowController;
        mResources = resources;
        mSourceProxy = sourceProxy;

        try {
@@ -120,8 +135,9 @@ public class CommunalSourceImpl implements CommunalSource {
                CallbackToFutureAdapter.getFuture(completer -> {
                    final SurfaceView view = new SurfaceView(context);
                    completer.set(new CommunalViewResult(view,
                            new CommunalSurfaceViewController(view, mMainExecutor,
                                    mCommunalStateController, this)));
                            new CommunalSurfaceViewController(view, mResources, mMainExecutor,
                                    mCommunalStateController, mNotificationShadeWindowController,
                                    this)));
                    return "CommunalSourceImpl::requestCommunalSurface::getCommunalSurface";
                });

+65 −2
Original line number Diff line number Diff line
@@ -17,14 +17,21 @@
package com.android.systemui.communal.service;

import android.annotation.IntDef;
import android.content.res.Resources;
import android.graphics.Region;
import android.util.Log;
import android.view.IWindow;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import androidx.annotation.NonNull;

import com.android.systemui.R;
import com.android.systemui.communal.CommunalStateController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.util.Utils;
import com.android.systemui.util.ViewController;

import com.google.common.util.concurrent.ListenableFuture;
@@ -40,7 +47,10 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private final Executor mMainExecutor;
    private final CommunalStateController mCommunalStateController;
    private final NotificationShadeWindowController mNotificationShadeWindowController;
    private final CommunalSourceImpl mSource;
    private final Resources mResources;
    private final Region mSurfaceViewTouchableRegion;

    @IntDef({STATE_SURFACE_CREATED, STATE_SURFACE_VIEW_ATTACHED})
    private @interface State {}
@@ -73,18 +83,51 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {
        }
    };

    protected CommunalSurfaceViewController(SurfaceView view, Executor executor,
            CommunalStateController communalStateController, CommunalSourceImpl source) {
    private final View.OnLayoutChangeListener mOnLayoutChangeListener =
            new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
                int oldTop, int oldRight, int oldBottom) {
            // The margin for the status bar and keyguard indication are excluded from the tap
            // exclusion to preserve vertical swipes in this region.
            final int topMargin = mResources.getDimensionPixelSize(
                    Utils.shouldUseSplitNotificationShade(mResources)
                            ? R.dimen.split_shade_header_height
                            : R.dimen.notification_panel_margin_top);
            final int bottomMargin = mResources.getDimensionPixelSize(
                    R.dimen.keyguard_indication_bottom_padding);

            mSurfaceViewTouchableRegion.set(left, top + topMargin, right, bottom - bottomMargin);
            updateTouchExclusion();
        }
    };

    private CommunalStateController.Callback mCommunalStateCallback =
            new CommunalStateController.Callback() {
        @Override
        public void onCommunalViewOccludedChanged() {
            updateTouchExclusion();
        }
    };

    protected CommunalSurfaceViewController(SurfaceView view, Resources resources,
            Executor executor, CommunalStateController communalStateController,
            NotificationShadeWindowController notificationShadeWindowController,
            CommunalSourceImpl source) {
        super(view);
        mCommunalStateController = communalStateController;
        mSource = source;
        mResources = resources;
        mMainExecutor = executor;
        mNotificationShadeWindowController = notificationShadeWindowController;
        mSurfaceViewTouchableRegion = new Region();
    }

    @Override
    public void init() {
        super.init();
        mView.getHolder().addCallback(mSurfaceHolderCallback);
        mView.addOnLayoutChangeListener(mOnLayoutChangeListener);
    }

    private void setState(@State int state, boolean enabled) {
@@ -106,6 +149,24 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {
        mCurrentState = newState;

        showSurface(newState == STATE_CAN_SHOW_SURFACE);

        updateTouchExclusion();
    }

    private void updateTouchExclusion() {
        final IWindow window = IWindow.Stub.asInterface(mView.getWindowToken());
        final boolean excludeTouches = (mCurrentState & STATE_SURFACE_VIEW_ATTACHED) != 0
                && !mCommunalStateController.getCommunalViewOccluded();
        if (excludeTouches) {
            mNotificationShadeWindowController.setTouchExclusionRegion(mSurfaceViewTouchableRegion);
        } else {
            final Region emptyRegion = Region.obtain();
            mNotificationShadeWindowController.setTouchExclusionRegion(emptyRegion);
            emptyRegion.recycle();
        }
        // TODO(b/197036940): This is no longer necessary once the surface view is not on top of the
        // z-order.
        mView.setZOrderOnTop(excludeTouches);
    }

    private void showSurface(boolean show) {
@@ -163,10 +224,12 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {
    @Override
    protected void onViewAttached() {
        setState(STATE_SURFACE_VIEW_ATTACHED, true);
        mCommunalStateController.addCallback(mCommunalStateCallback);
    }

    @Override
    protected void onViewDetached() {
        mCommunalStateController.removeCallback(mCommunalStateCallback);
        setState(STATE_SURFACE_VIEW_ATTACHED, false);
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.statusbar;

import android.graphics.Region;
import android.view.ViewGroup;

import androidx.annotation.Nullable;
@@ -158,6 +159,9 @@ public interface NotificationShadeWindowController extends RemoteInputController
    /** Sets the state of whether the notification shade is touchable or not. */
    default void setNotTouchable(boolean notTouchable) {}

    /** Sets the region where touch is excluded from the parent window. */
    default void setTouchExclusionRegion(Region region) {}

    /** Sets a {@link OtherwisedCollapsedListener}. */
    default void setStateListener(OtherwisedCollapsedListener listener) {}

+17 −0
Original line number Diff line number Diff line
@@ -27,16 +27,20 @@ import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.graphics.Region;
import android.os.Binder;
import android.os.RemoteException;
import android.os.Trace;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.IWindow;
import android.view.IWindowSession;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;

import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dumpable;
@@ -506,6 +510,19 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
        }
    }

    @Override
    public void setTouchExclusionRegion(Region region) {
        try {
            final IWindowSession session = WindowManagerGlobal.getWindowSession();
            session.updateTapExcludeRegion(
                    IWindow.Stub.asInterface(getNotificationShadeView().getWindowToken()),
                    region);
        } catch (RemoteException e) {
            Log.e(TAG, "could not update the tap exclusion region:" + e);
        }
    }


    @Override
    public void setKeyguardShowing(boolean showing) {
        mCurrentState.mKeyguardShowing = showing;
Loading