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

Commit 07678d1f authored by Bryce Lee's avatar Bryce Lee Committed by Android (Google) Code Review
Browse files

Merge changes from topic "197568243"

* changes:
  Request new communal surface on layout changes.
  Always reparent SurfacePackage in setChildSurfacePackage.
  Allow for transparent communal views.
  Address communal UI glitches.
  Adjust the top of the communal view with keyguard.
  Suppress identical communal show requests.
parents 9b030f99 49af78d4
Loading
Loading
Loading
Loading
+6 −4
Original line number Original line Diff line number Diff line
@@ -1889,10 +1889,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
    public void setChildSurfacePackage(@NonNull SurfaceControlViewHost.SurfacePackage p) {
    public void setChildSurfacePackage(@NonNull SurfaceControlViewHost.SurfacePackage p) {
        final SurfaceControl lastSc = mSurfacePackage != null ?
        final SurfaceControl lastSc = mSurfacePackage != null ?
                mSurfacePackage.getSurfaceControl() : null;
                mSurfacePackage.getSurfaceControl() : null;
        if (mSurfaceControl != null && lastSc != null) {
        if (mSurfaceControl != null) {
            mTmpTransaction.reparent(lastSc, null).apply();
            if (lastSc != null) {
                mTmpTransaction.reparent(lastSc, null);
                mSurfacePackage.release();
                mSurfacePackage.release();
        } else if (mSurfaceControl != null) {
            }

            reparentSurfacePackage(mTmpTransaction, p);
            reparentSurfacePackage(mTmpTransaction, p);
            mTmpTransaction.apply();
            mTmpTransaction.apply();
        }
        }
+67 −13
Original line number Original line Diff line number Diff line
@@ -28,6 +28,10 @@ import com.android.keyguard.KeyguardVisibilityHelper;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -38,6 +42,8 @@ import com.google.common.util.concurrent.ListenableFuture;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.lang.ref.WeakReference;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;


import javax.inject.Inject;
import javax.inject.Inject;
@@ -49,13 +55,16 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>
    private static final String TAG = "CommunalController";
    private static final String TAG = "CommunalController";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final String STATE_LIST_FORMAT = "[%s]";
    private static final String STATE_LIST_FORMAT = "[%s]";
    private static final AnimationProperties COMMUNAL_ANIMATION_PROPERTIES =
            new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);


    private final Executor mMainExecutor;
    private final Executor mMainExecutor;
    private final CommunalStateController mCommunalStateController;
    private final CommunalStateController mCommunalStateController;
    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    private final KeyguardStateController mKeyguardStateController;
    private final KeyguardStateController mKeyguardStateController;
    private final StatusBarStateController mStatusBarStateController;
    private final StatusBarStateController mStatusBarStateController;
    private WeakReference<CommunalSource> mLastSource;
    private WeakReference<CommunalSource> mCurrentSource;
    private Optional<ShowRequest> mLastRequest = Optional.empty();
    private int mState;
    private int mState;
    private float mQsExpansion;
    private float mQsExpansion;
    private float mShadeExpansion;
    private float mShadeExpansion;
@@ -72,12 +81,43 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>
    // Only show communal view when keyguard is showing and not dozing.
    // Only show communal view when keyguard is showing and not dozing.
    private static final int SHOW_COMMUNAL_VIEW_REQUIRED_STATES = STATE_KEYGUARD_SHOWING;
    private static final int SHOW_COMMUNAL_VIEW_REQUIRED_STATES = STATE_KEYGUARD_SHOWING;
    private static final int SHOW_COMMUNAL_VIEW_INVALID_STATES =
    private static final int SHOW_COMMUNAL_VIEW_INVALID_STATES =
            STATE_DOZING | STATE_BOUNCER_SHOWING | STATE_KEYGUARD_OCCLUDED;
            STATE_DOZING | STATE_KEYGUARD_OCCLUDED;


    private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
    private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;


    private ViewController<? extends View> mCommunalViewController;
    private ViewController<? extends View> mCommunalViewController;


    private static class ShowRequest {
        private boolean mShouldShow;
        private WeakReference<CommunalSource> mSource;

        ShowRequest(boolean shouldShow, WeakReference<CommunalSource> source) {
            mShouldShow = shouldShow;
            mSource = source;
        }

        CommunalSource getSource() {
            return mSource != null ? mSource.get() : null;
        }

        boolean shouldShow() {
            return mShouldShow;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof ShowRequest)) return false;
            ShowRequest that = (ShowRequest) o;
            return mShouldShow == that.mShouldShow && Objects.equals(getSource(), that.getSource());
        }

        @Override
        public int hashCode() {
            return Objects.hash(mShouldShow, mSource);
        }
    }

    private KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
    private KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
            new KeyguardUpdateMonitorCallback() {
            new KeyguardUpdateMonitorCallback() {
                @Override
                @Override
@@ -176,9 +216,7 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>
        }
        }
    }
    }
    @Override
    @Override
    public void init() {
    public void onInit() {
        super.init();

        setState(STATE_KEYGUARD_SHOWING, mKeyguardStateController.isShowing());
        setState(STATE_KEYGUARD_SHOWING, mKeyguardStateController.isShowing());
        setState(STATE_DOZING, mStatusBarStateController.isDozing());
        setState(STATE_DOZING, mStatusBarStateController.isDozing());
    }
    }
@@ -253,18 +291,26 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>
    }
    }


    private void showSource() {
    private void showSource() {
        final ShowRequest request = new ShowRequest(
                (mState & SHOW_COMMUNAL_VIEW_REQUIRED_STATES) == SHOW_COMMUNAL_VIEW_REQUIRED_STATES
                    && (mState & SHOW_COMMUNAL_VIEW_INVALID_STATES) == 0
                    && mCurrentSource != null,
                mCurrentSource);

        if (mLastRequest.isPresent() && Objects.equals(mLastRequest.get(), request)) {
            return;
        }

        mLastRequest = Optional.of(request);

        // Make sure all necessary states are present for showing communal and all invalid states
        // Make sure all necessary states are present for showing communal and all invalid states
        // are absent
        // are absent
        mMainExecutor.execute(() -> {
        mMainExecutor.execute(() -> {
            final CommunalSource currentSource = mLastSource != null ? mLastSource.get() : null;

            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "showSource. currentSource:" + currentSource);
                Log.d(TAG, "showSource. currentSource:" + request.getSource());
            }
            }


            if ((mState & SHOW_COMMUNAL_VIEW_REQUIRED_STATES) == SHOW_COMMUNAL_VIEW_REQUIRED_STATES
            if (request.shouldShow()) {
                    && (mState & SHOW_COMMUNAL_VIEW_INVALID_STATES) == 0
                    && currentSource != null) {
                mView.removeAllViews();
                mView.removeAllViews();


                // Make view visible.
                // Make view visible.
@@ -273,7 +319,7 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>
                final Context context = mView.getContext();
                final Context context = mView.getContext();


                final ListenableFuture<CommunalSource.CommunalViewResult> listenableFuture =
                final ListenableFuture<CommunalSource.CommunalViewResult> listenableFuture =
                        currentSource.requestCommunalView(context);
                        request.getSource().requestCommunalView(context);


                if (listenableFuture == null) {
                if (listenableFuture == null) {
                    Log.e(TAG, "could not request communal view");
                    Log.e(TAG, "could not request communal view");
@@ -308,10 +354,18 @@ public class CommunalHostViewController extends ViewController<CommunalHostView>
     * @param source The new {@link CommunalSource}, {@code null} if not set.
     * @param source The new {@link CommunalSource}, {@code null} if not set.
     */
     */
    public void show(WeakReference<CommunalSource> source) {
    public void show(WeakReference<CommunalSource> source) {
        mLastSource = source;
        mCurrentSource = source;
        showSource();
        showSource();
    }
    }


    /**
     * Update position of the view with an optional animation
     */
    public void updatePosition(int y, boolean animate) {
        PropertyAnimator.setProperty(mView, AnimatableProperty.Y, y, COMMUNAL_ANIMATION_PROPERTIES,
                animate);
    }

    /**
    /**
     * Invoked when the quick settings is expanded.
     * Invoked when the quick settings is expanded.
     * @param expansionFraction the percentage the QS shade has been expanded.
     * @param expansionFraction the percentage the QS shade has been expanded.
+74 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2021 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.systemui.communal;

import android.util.Log;

import com.android.systemui.statusbar.phone.NotificationPanelViewController;

/**
 * {@link CommunalHostViewPositionAlgorithm} calculates the position of the communal view given
 * input such as the notification panel position.
 */
public class CommunalHostViewPositionAlgorithm {
    private static final String TAG = "CommunalPositionAlg";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    /**
     * @see NotificationPanelViewController#getExpandedFraction()
     */
    private float mPanelExpansion;

    /**
     * Height of {@link CommunalHostView}.
     */
    private int mCommunalHeight;

    /**
     * A data container for the result of the position algorithm.
     */
    public static class Result {
        /**
         * The y translation of the clock.
         */
        public int communalY;
    }

    /**
     * Sets the conditions under which the result should be calculated from.
     * @param panelExpansion The percentage the keyguard panel has been moved upwards.
     * @param communalHeight The height of the communal panel.
     */
    public void setup(float panelExpansion, int communalHeight) {
        if (DEBUG) {
            Log.d(TAG, "setup. panelExpansion:" + panelExpansion);
        }
        mPanelExpansion = panelExpansion;
        mCommunalHeight = communalHeight;
    }

    /**
     * Calculates the position based on factors input through {link {@link #setup(float, int)}}.
     * @param result The resulting calculations.
     */
    public void run(Result result) {
        // The panel expansion relates to the keyguard expansion. At full expansion, the communal
        // view should be aligned at the top (0). Otherwise, it should be shifted offscreen by the
        // unexpanded amount.
        result.communalY = (int) ((1 - mPanelExpansion) * -mCommunalHeight);
    }
}
+44 −7
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ import com.google.common.util.concurrent.ListenableFuture;


import java.lang.ref.WeakReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;


import javax.inject.Inject;
import javax.inject.Inject;
@@ -78,6 +79,45 @@ public class CommunalSourceImpl implements CommunalSource {
        }
        }
    }
    }


    static class Request {
        private final int mWidth;
        private final int mHeight;
        private final int mDisplayId;
        private final IBinder mHostToken;

        Request(int width, int height, int displayId, IBinder hostToken) {
            mWidth = width;
            mHeight = height;
            mDisplayId = displayId;
            mHostToken = hostToken;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Request)) return false;
            Request request = (Request) o;
            return mWidth == request.mWidth && mHeight == request.mHeight
                    && mDisplayId == request.mDisplayId && Objects.equals(mHostToken,
                    request.mHostToken);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mWidth, mHeight, mDisplayId, mHostToken);
        }

        @Override
        public String toString() {
            return "Request{"
                    + "mWidth=" + mWidth
                    + ", mHeight=" + mHeight
                    + ", mDisplayId=" + mDisplayId
                    + ", mHostToken=" + mHostToken
                    + '}';
        }
    }

    // mConnected is initialized to true as it is presumed instances are constructed with valid
    // mConnected is initialized to true as it is presumed instances are constructed with valid
    // proxies. The source can never be reconnected once the proxy has died. Once this value
    // proxies. The source can never be reconnected once the proxy has died. Once this value
    // becomes false, the source will always report disconnected to registering callbacks.
    // becomes false, the source will always report disconnected to registering callbacks.
@@ -148,18 +188,15 @@ public class CommunalSourceImpl implements CommunalSource {
     * Called internally to request a new {@link android.view.SurfaceControlViewHost.SurfacePackage}
     * Called internally to request a new {@link android.view.SurfaceControlViewHost.SurfacePackage}
     * for showing communal content.
     * for showing communal content.
     *
     *
     * @param hostToken The HostToken necessary to generate a {@link SurfaceControlViewHost}.
     * @param request A request with the parameters for the new communal surface.
     * @param displayId The id of the display the surface will be shown on.
     * @param width     The width of the surface.
     * @param height    The height of the surface.
     * @return A future that returns the resulting
     * @return A future that returns the resulting
     * {@link android.view.SurfaceControlViewHost.SurfacePackage}.
     * {@link android.view.SurfaceControlViewHost.SurfacePackage}.
     */
     */
    protected ListenableFuture<SurfaceControlViewHost.SurfacePackage> requestCommunalSurface(
    protected ListenableFuture<SurfaceControlViewHost.SurfacePackage> requestCommunalSurface(
            IBinder hostToken, int displayId, int width, int height) {
            Request request) {
        return CallbackToFutureAdapter.getFuture(completer -> {
        return CallbackToFutureAdapter.getFuture(completer -> {
            mSourceProxy.getCommunalSurface(hostToken, width, height, displayId,
            mSourceProxy.getCommunalSurface(request.mHostToken, request.mWidth, request.mHeight,
                    new ICommunalSurfaceCallback.Stub() {
                    request.mDisplayId, new ICommunalSurfaceCallback.Stub() {
                        @Override
                        @Override
                        public void onSurface(
                        public void onSurface(
                                SurfaceControlViewHost.SurfacePackage surfacePackage) {
                                SurfaceControlViewHost.SurfacePackage surfacePackage) {
+23 −6
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.communal.service;


import android.annotation.IntDef;
import android.annotation.IntDef;
import android.content.res.Resources;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Region;
import android.graphics.Region;
import android.util.Log;
import android.util.Log;
import android.view.IWindow;
import android.view.IWindow;
@@ -36,6 +37,7 @@ import com.android.systemui.util.ViewController;


import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFuture;


import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;


/**
/**
@@ -63,6 +65,8 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {


    private int mCurrentState;
    private int mCurrentState;


    private Optional<CommunalSourceImpl.Request> mLastRequest = Optional.empty();

    // The current in-flight request for a surface package.
    // The current in-flight request for a surface package.
    private ListenableFuture<SurfaceControlViewHost.SurfacePackage> mCurrentSurfaceFuture;
    private ListenableFuture<SurfaceControlViewHost.SurfacePackage> mCurrentSurfaceFuture;


@@ -99,6 +103,9 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {


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

            // Trigger showing (or hiding) surface based on new dimensions.
            showSurface();
        }
        }
    };
    };


@@ -125,6 +132,7 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {


    @Override
    @Override
    protected void onInit() {
    protected void onInit() {
        mView.getHolder().setFormat(PixelFormat.TRANSPARENT);
        mView.getHolder().addCallback(mSurfaceHolderCallback);
        mView.getHolder().addCallback(mSurfaceHolderCallback);
        mView.addOnLayoutChangeListener(mOnLayoutChangeListener);
        mView.addOnLayoutChangeListener(mOnLayoutChangeListener);
    }
    }
@@ -147,7 +155,7 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {


        mCurrentState = newState;
        mCurrentState = newState;


        showSurface(newState == STATE_CAN_SHOW_SURFACE);
        showSurface();


        updateTouchExclusion();
        updateTouchExclusion();
    }
    }
@@ -165,25 +173,34 @@ public class CommunalSurfaceViewController extends ViewController<SurfaceView> {
        }
        }
    }
    }


    private void showSurface(boolean show) {
    private void showSurface() {
        mView.setWillNotDraw(false);
        mView.setWillNotDraw(false);


        if (!show) {
        if (mCurrentState != STATE_CAN_SHOW_SURFACE) {
            // If the surface is no longer showing, cancel any in-flight requests.
            // If the surface is no longer showing, cancel any in-flight requests.
            if (mCurrentSurfaceFuture != null) {
            if (mCurrentSurfaceFuture != null) {
                mCurrentSurfaceFuture.cancel(true);
                mCurrentSurfaceFuture.cancel(true);
                mCurrentSurfaceFuture = null;
                mCurrentSurfaceFuture = null;
            }
            }


            mLastRequest = Optional.empty();
            mView.setWillNotDraw(true);
            mView.setWillNotDraw(true);
            return;
            return;
        }
        }


        final CommunalSourceImpl.Request request = new CommunalSourceImpl.Request(
                mView.getMeasuredWidth(), mView.getMeasuredHeight(),
                mView.getDisplay().getDisplayId(), mView.getHostToken());

        if (mLastRequest.isPresent() && mLastRequest.get().equals(request)) {
            return;
        }

        mLastRequest = Optional.of(request);

        // Since this method is only called when the state has changed, mCurrentSurfaceFuture should
        // Since this method is only called when the state has changed, mCurrentSurfaceFuture should
        // be null here.
        // be null here.
        mCurrentSurfaceFuture = mSource.requestCommunalSurface(mView.getHostToken(),
        mCurrentSurfaceFuture = mSource.requestCommunalSurface(request);
                        mView.getDisplay().getDisplayId(), mView.getMeasuredWidth(),
                        mView.getMeasuredHeight());


        mCurrentSurfaceFuture.addListener(new Runnable() {
        mCurrentSurfaceFuture.addListener(new Runnable() {
            @Override
            @Override
Loading