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

Commit 199e3683 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I2d9f1a2d,I01fd8ba6

* changes:
  Ensure PIP retains bounds on device rotation.
  Fix wrong bounds being used in landscape.
parents 706d9124 cd1ff646
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -2943,14 +2943,16 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
        }
        case GET_DEFAULT_PICTURE_IN_PICTURE_BOUNDS_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            Rect r = getDefaultPictureInPictureBounds();
            final int displayId = data.readInt();
            Rect r = getDefaultPictureInPictureBounds(displayId);
            reply.writeNoException();
            r.writeToParcel(reply, 0);
            return true;
        }
        case GET_PICTURE_IN_PICTURE_MOVEMENT_BOUNDS_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            Rect r = getPictureInPictureMovementBounds();
            final int displayId = data.readInt();
            Rect r = getPictureInPictureMovementBounds(displayId);
            reply.writeNoException();
            r.writeToParcel(reply, 0);
            return true;
@@ -7026,11 +7028,12 @@ class ActivityManagerProxy implements IActivityManager
    }

    @Override
    public Rect getDefaultPictureInPictureBounds() throws RemoteException
    public Rect getDefaultPictureInPictureBounds(int displayId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeInt(displayId);
        mRemote.transact(GET_DEFAULT_PICTURE_IN_PICTURE_BOUNDS_TRANSACTION, data, reply, 0);
        reply.readException();
        Rect rect = Rect.CREATOR.createFromParcel(reply);
@@ -7040,11 +7043,12 @@ class ActivityManagerProxy implements IActivityManager
    }

    @Override
    public Rect getPictureInPictureMovementBounds() throws RemoteException
    public Rect getPictureInPictureMovementBounds(int displayId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeInt(displayId);
        mRemote.transact(GET_PICTURE_IN_PICTURE_MOVEMENT_BOUNDS_TRANSACTION, data, reply, 0);
        reply.readException();
        Rect rect = Rect.CREATOR.createFromParcel(reply);
+2 −2
Original line number Diff line number Diff line
@@ -662,12 +662,12 @@ public interface IActivityManager extends IInterface {
    /**
     * @return the default bounds of the PIP on the default display.
     */
    public Rect getDefaultPictureInPictureBounds() throws RemoteException;
    public Rect getDefaultPictureInPictureBounds(int displayId) throws RemoteException;

    /**
     * @return the movement bounds of the PIP on the default display.
     */
    public Rect getPictureInPictureMovementBounds() throws RemoteException;
    public Rect getPictureInPictureMovementBounds(int displayId) throws RemoteException;

    public int setVrMode(IBinder token, boolean enabled, ComponentName packageName)
            throws RemoteException;
+1 −1
Original line number Diff line number Diff line
@@ -444,7 +444,7 @@ interface IWindowManager
    /**
     * Retrieves the current stable insets from the primary display.
     */
    void getStableInsets(out Rect outInsets);
    void getStableInsets(int displayId, out Rect outInsets);

    /**
     * Register shortcut key. Shortcut code is packed as:
+174 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.internal.policy;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.view.Gravity;
import android.view.ViewConfiguration;
import android.widget.Scroller;

import java.util.ArrayList;

/**
 * Calculates the snap targets and the snap position for the PIP given a position and a velocity.
 * All bounds are relative to the display top/left.
 */
public class PipSnapAlgorithm {

    // Allows snapping to the four corners
    private static final int SNAP_MODE_CORNERS_ONLY = 0;
    // Allows snapping to the four corners and the mid-points on the long edge in each orientation
    private static final int SNAP_MODE_CORNERS_AND_SIDES = 1;
    // Allows snapping to anywhere along the edge of the screen
    private static final int SNAP_MODE_EDGE = 2;

    private static final float SCROLL_FRICTION_MULTIPLIER = 8f;

    private final Context mContext;

    private final ArrayList<Integer> mSnapGravities = new ArrayList<>();
    private final int mSnapMode = SNAP_MODE_CORNERS_ONLY;

    private final Scroller mScroller;
    private final Rect mDisplayBounds = new Rect();
    private int mOrientation = Configuration.ORIENTATION_UNDEFINED;

    public PipSnapAlgorithm(Context context, int displayId) {
        final DisplayManager displayManager =
                (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
        final ViewConfiguration viewConfig = ViewConfiguration.get(context);
        final Point displaySize = new Point();
        displayManager.getDisplay(displayId).getRealSize(displaySize);
        mContext = context;
        mDisplayBounds.set(0, 0, displaySize.x, displaySize.y);
        mOrientation = context.getResources().getConfiguration().orientation;
        mScroller = new Scroller(context);
        mScroller.setFriction(viewConfig.getScrollFriction() * SCROLL_FRICTION_MULTIPLIER);
        calculateSnapTargets();
    }

    /**
     * @return the closest absolute snap stack bounds for the given {@param stackBounds} moving at
     * the given {@param velocityX} and {@param velocityY}.  The {@param movementBounds} should be
     * those for the given {@param stackBounds}.
     */
    public Rect findClosestSnapBounds(Rect movementBounds, Rect stackBounds, float velocityX,
            float velocityY) {
        final Rect finalStackBounds = new Rect(stackBounds);
        mScroller.fling(stackBounds.left, stackBounds.top,
                (int) velocityX, (int) velocityY,
                movementBounds.left, movementBounds.right,
                movementBounds.top, movementBounds.bottom);
        finalStackBounds.offsetTo(mScroller.getFinalX(), mScroller.getFinalY());
        mScroller.abortAnimation();
        return findClosestSnapBounds(movementBounds, finalStackBounds);
    }

    /**
     * @return the closest absolute snap stack bounds for the given {@param stackBounds}.  The
     * {@param movementBounds} should be those for the given {@param stackBounds}.
     */
    public Rect findClosestSnapBounds(Rect movementBounds, Rect stackBounds) {
        final Rect pipBounds = new Rect(movementBounds.left, movementBounds.top,
                movementBounds.right + stackBounds.width(),
                movementBounds.bottom + stackBounds.height());
        final Rect newBounds = new Rect(stackBounds);
        if (mSnapMode == SNAP_MODE_EDGE) {
            // Find the closest edge to the given stack bounds and snap to it
            final int fromLeft = stackBounds.left - movementBounds.left;
            final int fromTop = stackBounds.top - movementBounds.top;
            final int fromRight = movementBounds.right - stackBounds.left;
            final int fromBottom = movementBounds.bottom - stackBounds.top;
            if (fromLeft <= fromTop && fromLeft <= fromRight && fromLeft <= fromBottom) {
                newBounds.offset(-fromLeft, 0);
            } else if (fromTop <= fromLeft && fromTop <= fromRight && fromTop <= fromBottom) {
                newBounds.offset(0, -fromTop);
            } else if (fromRight < fromLeft && fromRight < fromTop && fromRight < fromBottom) {
                newBounds.offset(fromRight, 0);
            } else {
                newBounds.offset(0, fromBottom);
            }
        } else {
            // Find the closest snap point
            final Rect tmpBounds = new Rect();
            final Point[] snapTargets = new Point[mSnapGravities.size()];
            for (int i = 0; i < mSnapGravities.size(); i++) {
                Gravity.apply(mSnapGravities.get(i), stackBounds.width(), stackBounds.height(),
                        pipBounds, 0, 0, tmpBounds);
                snapTargets[i] = new Point(tmpBounds.left, tmpBounds.top);
            }
            Point snapTarget = findClosestPoint(stackBounds.left, stackBounds.top, snapTargets);
            newBounds.offsetTo(snapTarget.x, snapTarget.y);
        }
        return newBounds;
    }

    /**
     * @return the closest point in {@param points} to the given {@param x} and {@param y}.
     */
    private Point findClosestPoint(int x, int y, Point[] points) {
        Point closestPoint = null;
        float minDistance = Float.MAX_VALUE;
        for (Point p : points) {
            float distance = distanceToPoint(p, x, y);
            if (distance < minDistance) {
                closestPoint = p;
                minDistance = distance;
            }
        }
        return closestPoint;
    }

    /**
     * @return the distance between point {@param p} and the given {@param x} and {@param y}.
     */
    private float distanceToPoint(Point p, int x, int y) {
        return PointF.length(p.x - x, p.y - y);
    }

    /**
     * Calculate the snap targets for the discrete snap modes.
     */
    private void calculateSnapTargets() {
        mSnapGravities.clear();
        switch (mSnapMode) {
            case SNAP_MODE_CORNERS_AND_SIDES:
                if (mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
                    mSnapGravities.add(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
                    mSnapGravities.add(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
                } else {
                    mSnapGravities.add(Gravity.CENTER_VERTICAL | Gravity.LEFT);
                    mSnapGravities.add(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
                }
                // Fall through
            case SNAP_MODE_CORNERS_ONLY:
                mSnapGravities.add(Gravity.TOP | Gravity.LEFT);
                mSnapGravities.add(Gravity.TOP | Gravity.RIGHT);
                mSnapGravities.add(Gravity.BOTTOM | Gravity.LEFT);
                mSnapGravities.add(Gravity.BOTTOM | Gravity.RIGHT);
                break;
            default:
                // Skip otherwise
                break;
        }
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -52,7 +52,9 @@ public class PipManager {
    /**
     * Updates the PIP per configuration changed.
     */
    public void onConfigurationChanged() {}
    public void onConfigurationChanged() {
        mTouchHandler.onConfigurationChanged();
    }

    /**
     * Gets an instance of {@link PipManager}.
Loading