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

Commit 94891df6 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Move the overflow ui to the bubble window"

parents 38226653 ebf69036
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
  ~ limitations under the License
  -->

<LinearLayout
<com.android.wm.shell.bubbles.BubbleOverflowContainerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bubble_overflow_container"
    android:layout_width="match_parent"
@@ -34,8 +34,8 @@

    <LinearLayout
        android:id="@+id/bubble_overflow_empty_state"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="@dimen/bubble_overflow_empty_state_padding"
        android:paddingRight="@dimen/bubble_overflow_empty_state_padding"
        android:orientation="vertical"
@@ -69,4 +69,4 @@
            android:paddingBottom="@dimen/bubble_empty_overflow_subtitle_padding"
            android:gravity="center"/>
    </LinearLayout>
</LinearLayout>
</com.android.wm.shell.bubbles.BubbleOverflowContainerView>
+53 −32
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.wm.shell.bubbles.BubbleOverflowActivity.EXTRA_BUBBLE_CONTROLLER;

import android.annotation.NonNull;
import android.annotation.SuppressLint;
@@ -37,14 +36,16 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
@@ -77,6 +78,7 @@ public class BubbleExpandedView extends LinearLayout {

    private AlphaOptimizedButton mSettingsIcon;
    private TaskView mTaskView;
    private BubbleOverflowContainerView mOverflowView;

    private int mTaskId = INVALID_TASK_ID;

@@ -125,6 +127,7 @@ public class BubbleExpandedView extends LinearLayout {
            if (mDestroyed || mInitialized) {
                return;
            }

            // Custom options so there is no activity transition animation
            ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(),
                    0 /* enterResId */, 0 /* exitResId */);
@@ -307,15 +310,25 @@ public class BubbleExpandedView extends LinearLayout {
     * Initialize {@link BubbleController} and {@link BubbleStackView} here, this method must need
     * to be called after view inflate.
     */
    void initialize(BubbleController controller, BubbleStackView stackView) {
    void initialize(BubbleController controller, BubbleStackView stackView, boolean isOverflow) {
        mController = controller;
        mStackView = stackView;
        mIsOverflow = isOverflow;
        mPositioner = mController.getPositioner();

        if (mIsOverflow) {
            mOverflowView = (BubbleOverflowContainerView) LayoutInflater.from(getContext()).inflate(
                    R.layout.bubble_overflow_container, null /* root */);
            mOverflowView.setBubbleController(mController);
            mExpandedViewContainer.addView(mOverflowView);
            bringChildToFront(mOverflowView);
            mSettingsIcon.setVisibility(GONE);
        } else {
            mTaskView = new TaskView(mContext, mController.getTaskOrganizer());
            mTaskView.setListener(mContext.getMainExecutor(), mTaskViewListener);
            mExpandedViewContainer.addView(mTaskView);
            bringChildToFront(mTaskView);
        mTaskView.setListener(mContext.getMainExecutor(), mTaskViewListener);
        mPositioner = mController.getPositioner();
        }
    }

    void updateDimensions() {
@@ -390,6 +403,17 @@ public class BubbleExpandedView extends LinearLayout {
    /** Return a GraphicBuffer with the contents of the task view surface. */
    @Nullable
    SurfaceControl.ScreenshotHardwareBuffer snapshotActivitySurface() {
        if (mIsOverflow) {
            // For now, just snapshot the view and return it as a hw buffer so that the animation
            // code for both the tasks and overflow can be the same
            Picture p = new Picture();
            mOverflowView.draw(
                    p.beginRecording(mOverflowView.getWidth(), mOverflowView.getHeight()));
            p.endRecording();
            Bitmap snapshot = Bitmap.createBitmap(p);
            return new SurfaceControl.ScreenshotHardwareBuffer(snapshot.getHardwareBuffer(),
                    snapshot.getColorSpace(), false /* containsSecureLayers */);
        }
        if (mTaskView == null || mTaskView.getSurfaceControl() == null) {
            return null;
        }
@@ -400,6 +424,11 @@ public class BubbleExpandedView extends LinearLayout {
    }

    int[] getTaskViewLocationOnScreen() {
        if (mIsOverflow) {
            // This is only used for animating away the surface when switching bubbles, just use the
            // view location on screen for now to allow us to use the same animation code with tasks
            return mOverflowView.getLocationOnScreen();
        }
        if (mTaskView != null) {
            return mTaskView.getLocationOnScreen();
        } else {
@@ -450,10 +479,7 @@ public class BubbleExpandedView extends LinearLayout {
        final float alpha = visibility ? 1f : 0f;

        mPointerView.setAlpha(alpha);
        if (mTaskView == null) {
            return;
        }
        if (alpha != mTaskView.getAlpha()) {
        if (mTaskView != null) {
            mTaskView.setAlpha(alpha);
        }
    }
@@ -467,19 +493,6 @@ public class BubbleExpandedView extends LinearLayout {
        return mTaskId;
    }

    public void setOverflow(boolean overflow) {
        mIsOverflow = overflow;

        Intent target = new Intent(mContext, BubbleOverflowActivity.class);
        target.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
        Bundle extras = new Bundle();
        extras.putBinder(EXTRA_BUBBLE_CONTROLLER, ObjectWrapper.wrap(mController));
        target.putExtras(extras);
        mPendingIntent = PendingIntent.getActivity(mContext, 0 /* requestCode */,
                target, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        mSettingsIcon.setVisibility(GONE);
    }

    /**
     * Sets the bubble used to populate this view.
     */
@@ -511,7 +524,8 @@ public class BubbleExpandedView extends LinearLayout {

            if (isNew) {
                mPendingIntent = mBubble.getBubbleIntent();
                if (mPendingIntent != null || mBubble.hasMetadataShortcutId()) {
                if ((mPendingIntent != null || mBubble.hasMetadataShortcutId())
                        && mTaskView != null) {
                    setContentVisibility(false);
                    mTaskView.setVisibility(VISIBLE);
                }
@@ -552,13 +566,19 @@ public class BubbleExpandedView extends LinearLayout {
            desiredHeight = Math.max(desiredHeight, mMinHeight);
            float height = Math.min(desiredHeight, getMaxExpandedHeight());
            height = Math.max(height, mMinHeight);
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mTaskView.getLayoutParams();
            FrameLayout.LayoutParams lp = mIsOverflow
                    ? (FrameLayout.LayoutParams) mOverflowView.getLayoutParams()
                    : (FrameLayout.LayoutParams) mTaskView.getLayoutParams();
            mNeedsNewHeight = lp.height != height;
            if (!mImeVisible) {
                // If the ime is visible... don't adjust the height because that will cause
                // a configuration change and the ime will be lost.
                lp.height = (int) height;
                if (mIsOverflow) {
                    mOverflowView.setLayoutParams(lp);
                } else {
                    mTaskView.setLayoutParams(lp);
                }
                mNeedsNewHeight = false;
            }
            if (DEBUG_BUBBLE_EXPANDED_VIEW) {
@@ -602,6 +622,9 @@ public class BubbleExpandedView extends LinearLayout {
            updateHeight();
            mTaskView.onLocationChanged();
        }
        if (mIsOverflow) {
            mOverflowView.show();
        }
    }

    /**
@@ -637,8 +660,8 @@ public class BubbleExpandedView extends LinearLayout {

    /**
     * Cleans up anything related to the task and TaskView. If this view should be reused after this
     * method is called, then {@link #initialize(BubbleController, BubbleStackView)} must be invoked
     * first.
     * method is called, then {@link #initialize(BubbleController, BubbleStackView, boolean)} must
     * be invoked first.
     */
    public void cleanUpExpandedState() {
        if (DEBUG_BUBBLE_EXPANDED_VIEW) {
@@ -653,8 +676,6 @@ public class BubbleExpandedView extends LinearLayout {
        }
        if (mTaskView != null) {
            mTaskView.release();
        }
        if (mTaskView != null) {
            removeView(mTaskView);
            mTaskView = null;
        }
+1 −2
Original line number Diff line number Diff line
@@ -65,8 +65,7 @@ class BubbleOverflow(

    /** Call before use and again if cleanUpExpandedState was called.  */
    fun initialize(controller: BubbleController) {
        getExpandedView()?.initialize(controller, controller.stackView)
        getExpandedView()?.setOverflow(true)
        getExpandedView()?.initialize(controller, controller.stackView, true /* isOverflow */)
    }

    fun cleanUpExpandedState() {
+49 −52
Original line number Diff line number Diff line
@@ -29,16 +29,21 @@ import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Bundle;
import android.os.IBinder;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

@@ -50,10 +55,9 @@ import java.util.List;
import java.util.function.Consumer;

/**
 * Activity for showing aged out bubbles.
 * Must be public to be accessible to androidx...AppComponentFactory
 * Container view for showing aged out bubbles.
 */
public class BubbleOverflowActivity extends Activity {
public class BubbleOverflowContainerView extends LinearLayout {
    static final String EXTRA_BUBBLE_CONTROLLER = "bubble_controller";

    private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleOverflowActivity" : TAG_BUBBLES;
@@ -95,37 +99,55 @@ public class BubbleOverflowActivity extends Activity {
        }
    }

    public BubbleOverflowContainerView(Context context) {
        super(context);
    }

    public BubbleOverflowContainerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public BubbleOverflowContainerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public BubbleOverflowContainerView(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public void setBubbleController(BubbleController controller) {
        mController = controller;
    }

    public void show() {
        setVisibility(View.VISIBLE);
        updateOverflow();
    }

    public void hide() {
        setVisibility(View.INVISIBLE);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.bubble_overflow_activity);
    protected void onFinishInflate() {
        super.onFinishInflate();

        mRecyclerView = findViewById(R.id.bubble_overflow_recycler);
        mEmptyState = findViewById(R.id.bubble_overflow_empty_state);
        mEmptyStateTitle = findViewById(R.id.bubble_overflow_empty_title);
        mEmptyStateSubtitle = findViewById(R.id.bubble_overflow_empty_subtitle);
        mEmptyStateImage = findViewById(R.id.bubble_overflow_empty_state_image);

        Intent intent = getIntent();
        if (intent != null && intent.getExtras() != null) {
            IBinder binder = intent.getExtras().getBinder(EXTRA_BUBBLE_CONTROLLER);
            if (binder instanceof ObjectWrapper) {
                mController = ((ObjectWrapper<BubbleController>) binder).get();
                updateOverflow();
            }
        } else {
            Log.w(TAG, "Bubble overflow activity created without bubble controller!");
        }
    }

    void updateOverflow() {
        Resources res = getResources();
        final int columns = res.getInteger(R.integer.bubbles_overflow_columns);
        mRecyclerView.setLayoutManager(
                new NoScrollGridLayoutManager(getApplicationContext(), columns));
                new NoScrollGridLayoutManager(getContext(), columns));

        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        getContext().getDisplay().getMetrics(displayMetrics);

        final int overflowPadding = res.getDimensionPixelSize(R.dimen.bubble_overflow_padding);
        final int recyclerViewWidth = displayMetrics.widthPixels - (overflowPadding * 2);
@@ -137,7 +159,7 @@ public class BubbleOverflowActivity extends Activity {
                - res.getDimensionPixelSize(R.dimen.bubble_overflow_padding);
        final int viewHeight = recyclerViewHeight / rows;

        mAdapter = new BubbleOverflowAdapter(getApplicationContext(), mOverflowBubbles,
        mAdapter = new BubbleOverflowAdapter(getContext(), mOverflowBubbles,
                mController::promoteBubbleFromOverflow,
                mController.getPositioner(),
                viewWidth, viewHeight);
@@ -146,6 +168,11 @@ public class BubbleOverflowActivity extends Activity {
        mOverflowBubbles.clear();
        mOverflowBubbles.addAll(mController.getOverflowBubbles());
        mAdapter.notifyDataSetChanged();

        // Currently BubbleExpandedView.mExpandedViewContainer is WRAP_CONTENT so use the same
        // width we would use for the recycler view
        LayoutParams lp = (LayoutParams) mEmptyState.getLayoutParams();
        lp.width = recyclerViewWidth;
        updateEmptyStateVisibility();

        mController.setOverflowListener(mDataListener);
@@ -172,12 +199,12 @@ public class BubbleOverflowActivity extends Activity {
                ? res.getDrawable(R.drawable.bubble_ic_empty_overflow_dark)
                : res.getDrawable(R.drawable.bubble_ic_empty_overflow_light));

        findViewById(android.R.id.content)
        findViewById(R.id.bubble_overflow_container)
                .setBackgroundColor(isNightMode
                        ? res.getColor(R.color.bubbles_dark)
                        : res.getColor(R.color.bubbles_light));

        final TypedArray typedArray = getApplicationContext().obtainStyledAttributes(
        final TypedArray typedArray = getContext().obtainStyledAttributes(
                new int[]{android.R.attr.colorBackgroundFloating,
                        android.R.attr.textColorSecondary});
        int bgColor = typedArray.getColor(0, isNightMode ? Color.BLACK : Color.WHITE);
@@ -222,36 +249,6 @@ public class BubbleOverflowActivity extends Activity {
            }
        }
    };

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onRestart() {
        super.onRestart();
    }

    @Override
    public void onResume() {
        super.onResume();
        updateOverflow();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    public void onDestroy() {
        super.onDestroy();
    }
}

class BubbleOverflowAdapter extends RecyclerView.Adapter<BubbleOverflowAdapter.ViewHolder> {
+1 −1
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask

                info.expandedView = (BubbleExpandedView) inflater.inflate(
                        R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
                info.expandedView.initialize(controller, stackView);
                info.expandedView.initialize(controller, stackView, false /* isOverflow */);
            }

            if (b.getShortcutInfo() != null) {
Loading