Merge "TRON refinements for multi-window" into nyc-dev am: a74888d

am: e203cde

* commit 'e203cdefa1cc34057230ad83fdc5ef172e96f080':
  TRON refinements for multi-window

Change-Id: I2edd0f1e9b851234c21e42cd2e22e127a155e21f
This commit is contained in:
TreeHugger Robot
2016-04-13 04:28:59 +00:00
committed by android-build-merger
16 changed files with 161 additions and 38 deletions

View File

@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Matrix;
@@ -1305,6 +1306,12 @@ public class ActivityManager {
*/
public boolean isDockable;
/**
* The resize mode of the task. See {@link ActivityInfo#resizeMode}.
* @hide
*/
public int resizeMode;
public RecentTaskInfo() {
}
@@ -1349,6 +1356,7 @@ public class ActivityManager {
dest.writeInt(0);
}
dest.writeInt(isDockable ? 1 : 0);
dest.writeInt(resizeMode);
}
public void readFromParcel(Parcel source) {
@@ -1372,6 +1380,7 @@ public class ActivityManager {
bounds = source.readInt() > 0 ?
Rect.CREATOR.createFromParcel(source) : null;
isDockable = source.readInt() == 1;
resizeMode = source.readInt();
}
public static final Creator<RecentTaskInfo> CREATOR
@@ -1560,6 +1569,12 @@ public class ActivityManager {
*/
public boolean isDockable;
/**
* The resize mode of the task. See {@link ActivityInfo#resizeMode}.
* @hide
*/
public int resizeMode;
public RunningTaskInfo() {
}
@@ -1583,6 +1598,7 @@ public class ActivityManager {
dest.writeInt(numActivities);
dest.writeInt(numRunning);
dest.writeInt(isDockable ? 1 : 0);
dest.writeInt(resizeMode);
}
public void readFromParcel(Parcel source) {
@@ -1599,6 +1615,7 @@ public class ActivityManager {
numActivities = source.readInt();
numRunning = source.readInt();
isDockable = source.readInt() != 0;
resizeMode = source.readInt();
}
public static final Creator<RunningTaskInfo> CREATOR = new Creator<RunningTaskInfo>() {

View File

@@ -32,7 +32,8 @@ public interface RecentsComponent {
/**
* Docks the top-most task and opens recents.
*/
boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds);
boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds,
int metricsDockAction);
/**
* Called during a drag-from-navbar-in gesture.

View File

@@ -23,6 +23,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
@@ -36,10 +37,13 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.EventLog;
import android.util.Log;
import android.util.MutableBoolean;
import android.view.Display;
import android.view.View;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
@@ -78,6 +82,10 @@ public class Recents extends SystemUI
private final static String ACTION_HIDE_RECENTS = "com.android.systemui.recents.ACTION_HIDE";
private final static String ACTION_TOGGLE_RECENTS = "com.android.systemui.recents.ACTION_TOGGLE";
private static final String COUNTER_WINDOW_SUPPORTED = "window_enter_supported";
private static final String COUNTER_WINDOW_UNSUPPORTED = "window_enter_unsupported";
private static final String COUNTER_WINDOW_INCOMPATIBLE = "window_enter_incompatible";
private static SystemServicesProxy sSystemServicesProxy;
private static RecentsDebugFlags sDebugFlags;
private static RecentsTaskLoader sTaskLoader;
@@ -393,7 +401,8 @@ public class Recents extends SystemUI
}
@Override
public boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds) {
public boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds,
int metricsDockAction) {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
if (!isUserSetup()) {
@@ -413,7 +422,12 @@ public class Recents extends SystemUI
boolean screenPinningActive = ssp.isScreenPinningActive();
boolean isTopTaskHome = topTask != null && SystemServicesProxy.isHomeStack(topTask.stackId);
if (topTask != null && !isTopTaskHome && !screenPinningActive) {
logDockAttempt(mContext, topTask.topActivity, topTask.resizeMode);
if (topTask.isDockable) {
if (metricsDockAction != -1) {
MetricsLogger.action(mContext, metricsDockAction,
topTask.topActivity.flattenToShortString());
}
if (sSystemServicesProxy.isSystemUser(currentUser)) {
mImpl.dockTopTask(topTask.id, dragMode, stackCreateMode, initialBounds);
} else {
@@ -444,6 +458,26 @@ public class Recents extends SystemUI
}
}
public static void logDockAttempt(Context ctx, ComponentName activity, int resizeMode) {
if (resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE) {
MetricsLogger.action(ctx, MetricsEvent.ACTION_WINDOW_DOCK_UNRESIZABLE,
activity.flattenToShortString());
}
MetricsLogger.count(ctx, getMetricsCounterForResizeMode(resizeMode), 1);
}
private static String getMetricsCounterForResizeMode(int resizeMode) {
switch (resizeMode) {
case ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE:
return COUNTER_WINDOW_UNSUPPORTED;
case ActivityInfo.RESIZE_MODE_RESIZEABLE:
case ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
return COUNTER_WINDOW_SUPPORTED;
default:
return COUNTER_WINDOW_INCOMPATIBLE;
}
}
@Override
public void onDraggingInRecents(float distanceFromTop) {
if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {

View File

@@ -206,7 +206,7 @@ public class RecentsTaskLoadPlan {
Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
thumbnail, title, titleDescription, dismissDescription, appInfoDescription,
activityColor, backgroundColor, isLaunchTarget, isStackTask, isSystemApp,
t.isDockable, t.bounds, t.taskDescription);
t.isDockable, t.bounds, t.taskDescription, t.resizeMode, t.topActivity);
allTasks.add(task);
affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);

View File

@@ -19,6 +19,7 @@ package com.android.systemui.recents.model;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
@@ -174,6 +175,15 @@ public class Task {
@ViewDebug.ExportedProperty(category="recents")
public boolean isDockable;
/**
* Resize mode. See {@link ActivityInfo#resizeMode}.
*/
@ViewDebug.ExportedProperty(category="recents")
public int resizeMode;
@ViewDebug.ExportedProperty(category="recents")
public ComponentName topActivity;
private ArrayList<TaskCallbacks> mCallbacks = new ArrayList<>();
public Task() {
@@ -184,7 +194,8 @@ public class Task {
Bitmap thumbnail, String title, String titleDescription, String dismissDescription,
String appInfoDescription, int colorPrimary, int colorBackground,
boolean isLaunchTarget, boolean isStackTask, boolean isSystemApp,
boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription) {
boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription,
int resizeMode, ComponentName topActivity) {
boolean isInAffiliationGroup = (affiliationTaskId != key.id);
boolean hasAffiliationGroupColor = isInAffiliationGroup && (affiliationColor != 0);
this.key = key;
@@ -206,6 +217,8 @@ public class Task {
this.isStackTask = isStackTask;
this.isSystemApp = isSystemApp;
this.isDockable = isDockable;
this.resizeMode = resizeMode;
this.topActivity = topActivity;
}
/**
@@ -231,6 +244,8 @@ public class Task {
this.isStackTask = o.isStackTask;
this.isSystemApp = o.isSystemApp;
this.isDockable = o.isDockable;
this.resizeMode = o.resizeMode;
this.topActivity = o.topActivity;
}
/**

View File

@@ -540,7 +540,8 @@ public class RecentsView extends FrameLayout {
mTransitionHelper.wrapStartedListener(startedListener),
true /* scaleUp */);
MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP);
MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP,
event.task.topActivity.flattenToShortString());
} else {
// Animate the overlay alpha back to 0
updateVisibleDockRegions(null, true /* isDefaultDockState */, -1,

View File

@@ -41,7 +41,6 @@ import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
/**
* Represents the dock regions for each orientation.
*/
@@ -163,6 +162,7 @@ public class RecentsViewTouchHandler {
mVisibleDockStates.clear();
if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()
&& mDividerSnapAlgorithm.isSplitScreenFeasible()) {
Recents.logDockAttempt(mRv.getContext(), event.task.topActivity, event.task.resizeMode);
if (!event.task.isDockable) {
EventBus.getDefault().send(new ShowIncompatibleAppOverlayEvent());
} else {

View File

@@ -102,8 +102,8 @@ public class ShortcutKeyDispatcher extends SystemUI
int dockMode = (shortcutCode == SC_DOCK_LEFT)
? ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
: ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
recents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, dockMode, null);
MetricsLogger.action(mContext, MetricsEvent.WINDOW_DOCK_SHORTCUTS);
recents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, dockMode, null,
MetricsEvent.WINDOW_DOCK_SHORTCUTS);
} else {
// If there is already a docked window, we respond by resizing the docking pane.
DividerView dividerView = getComponent(Divider.class).getView();
@@ -115,7 +115,8 @@ public class ShortcutKeyDispatcher extends SystemUI
DividerSnapAlgorithm.SnapTarget target = snapAlgorithm.cycleNonDismissTarget(
currentTarget, increment);
dividerView.startDragging(true /* animate */, false /* touching */);
dividerView.stopDragging(target.position, 0f, true /* avoidDismissStart */);
dividerView.stopDragging(target.position, 0f, true /* avoidDismissStart */,
true /* logMetrics */);
}
} catch (RemoteException e) {
Log.e(TAG, "handleDockKey() failed.");

View File

@@ -54,11 +54,14 @@ import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.internal.policy.DockedDividerUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Constants.Metrics;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
@@ -80,7 +83,13 @@ public class DividerView extends FrameLayout implements OnTouchListener,
static final long TOUCH_ANIMATION_DURATION = 150;
static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
private static final String TAG = "DividerView";
private static final int LOG_VALUE_RESIZE_50_50 = 0;
private static final int LOG_VALUE_RESIZE_DOCKED_SMALLER = 1;
private static final int LOG_VALUE_RESIZE_DOCKED_LARGER = 2;
private static final int LOG_VALUE_UNDOCK_MAX_DOCKED = 0;
private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1;
private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
private static final boolean SWAPPING_ENABLED = false;
@@ -313,9 +322,10 @@ public class DividerView extends FrameLayout implements OnTouchListener,
return mDockSide != WindowManager.DOCKED_INVALID;
}
public void stopDragging(int position, float velocity, boolean avoidDismissStart) {
public void stopDragging(int position, float velocity, boolean avoidDismissStart,
boolean logMetrics) {
mHandle.setTouching(false, true /* animate */);
fling(position, velocity, avoidDismissStart);
fling(position, velocity, avoidDismissStart, logMetrics);
mWindowManager.setSlippery(true);
releaseBackground();
}
@@ -413,22 +423,54 @@ public class DividerView extends FrameLayout implements OnTouchListener,
mVelocityTracker.computeCurrentVelocity(1000);
int position = calculatePosition(x, y);
stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()
: mVelocityTracker.getXVelocity(), false /* avoidDismissStart */);
: mVelocityTracker.getXVelocity(), false /* avoidDismissStart */,
true /* log */);
mMoving = false;
break;
}
return true;
}
private void logResizeEvent(SnapTarget snapTarget) {
if (snapTarget == mSnapAlgorithm.getDismissStartTarget()) {
MetricsLogger.action(
mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideTopLeft(mDockSide)
? LOG_VALUE_UNDOCK_MAX_OTHER
: LOG_VALUE_UNDOCK_MAX_DOCKED);
} else if (snapTarget == mSnapAlgorithm.getDismissEndTarget()) {
MetricsLogger.action(
mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideBottomRight(mDockSide)
? LOG_VALUE_UNDOCK_MAX_OTHER
: LOG_VALUE_UNDOCK_MAX_DOCKED);
} else if (snapTarget == mSnapAlgorithm.getMiddleTarget()) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
LOG_VALUE_RESIZE_50_50);
} else if (snapTarget == mSnapAlgorithm.getFirstSplitTarget()) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
dockSideTopLeft(mDockSide)
? LOG_VALUE_RESIZE_DOCKED_SMALLER
: LOG_VALUE_RESIZE_DOCKED_LARGER);
} else if (snapTarget == mSnapAlgorithm.getLastSplitTarget()) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
dockSideTopLeft(mDockSide)
? LOG_VALUE_RESIZE_DOCKED_LARGER
: LOG_VALUE_RESIZE_DOCKED_SMALLER);
}
}
private void convertToScreenCoordinates(MotionEvent event) {
event.setLocation(event.getRawX(), event.getRawY());
}
private void fling(int position, float velocity, boolean avoidDismissStart) {
private void fling(int position, float velocity, boolean avoidDismissStart,
boolean logMetrics) {
SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(position, velocity);
if (avoidDismissStart && snapTarget == mSnapAlgorithm.getDismissStartTarget()) {
snapTarget = mSnapAlgorithm.getFirstSplitTarget();
}
if (logMetrics) {
logResizeEvent(snapTarget);
}
ValueAnimator anim = getFlingAnimator(position, snapTarget);
mFlingAnimationUtils.apply(anim, position, snapTarget.position, velocity);
anim.start();

View File

@@ -1234,7 +1234,7 @@ public abstract class BaseStatusBar extends SystemUI implements
@Override
public void toggleSplitScreen() {
toggleSplitScreenMode();
toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
}
@Override
@@ -1310,9 +1310,12 @@ public abstract class BaseStatusBar extends SystemUI implements
/**
* Toggle docking the app window
*
* @return {@code true} if the app window is docked after the toggle, {@code false} otherwise.
* @param metricsDockAction the action to log when docking is successful, or -1 to not log
* anything on successful docking
* @param metricsUndockAction the action to log when undocking, or -1 to not log anything when
* undocking
*/
protected abstract boolean toggleSplitScreenMode();
protected abstract void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction);
/** Proxy for RecentsComponent */

View File

@@ -214,15 +214,14 @@ public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureL
< mContext.getResources().getDisplayMetrics().widthPixels / 2) {
createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
}
boolean docked = mRecentsComponent.dockTopTask(dragMode, createMode, initialBounds);
boolean docked = mRecentsComponent.dockTopTask(dragMode, createMode, initialBounds,
MetricsEvent.ACTION_WINDOW_DOCK_SWIPE);
if (docked) {
mDragMode = dragMode;
if (mDragMode == DRAG_MODE_DIVIDER) {
mDivider.getView().startDragging(false /* animate */, true /* touching*/);
}
mDockWindowTouchSlopExceeded = true;
MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_SWIPE);
return true;
}
}
@@ -250,7 +249,7 @@ public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureL
mIsVertical
? mVelocityTracker.getXVelocity()
: mVelocityTracker.getYVelocity(),
true /* avoidDismissStart */);
true /* avoidDismissStart */, false /* logMetrics */);
} else if (mDragMode == DRAG_MODE_RECENTS) {
mRecentsComponent.onDraggingInRecentsEnded(mVelocityTracker.getYVelocity());
}

View File

@@ -1177,31 +1177,26 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return false;
}
boolean initiallyDocked = WindowManagerProxy.getInstance().getDockSide()
== WindowManager.DOCKED_INVALID;
boolean dockedAtEnd = toggleSplitScreenMode();
if (dockedAtEnd != initiallyDocked) {
int logAction = dockedAtEnd ? MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS
: MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS;
MetricsLogger.action(mContext, logAction);
return true;
}
return false;
toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,
MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
return true;
}
};
@Override
protected boolean toggleSplitScreenMode() {
protected void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
if (mRecents == null) {
return false;
return;
}
int dockSide = WindowManagerProxy.getInstance().getDockSide();
if (dockSide == WindowManager.DOCKED_INVALID) {
return mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null);
mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null, metricsDockAction);
} else {
EventBus.getDefault().send(new UndockingTaskEvent());
return false;
if (metricsUndockAction != -1) {
MetricsLogger.action(mContext, metricsUndockAction);
}
}
}

View File

@@ -127,8 +127,7 @@ public class TvStatusBar extends BaseStatusBar {
}
@Override
protected boolean toggleSplitScreenMode() {
return false;
protected void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
}
@Override

View File

@@ -2138,6 +2138,20 @@ message MetricsEvent {
// Settings > Apps > Gear > Special Access > Premium SMS access
PREMIUM_SMS_ACCESS = 388;
// Logged when the user resizes the docked stack. Arguments:
// 0: Split 50:50
// 1: Docked smaller
// 2: Docked larger
ACTION_WINDOW_DOCK_RESIZE = 389;
// User exits split-screen by dragging the divider to the side of the screen. Arguments
// 0: Docked gets maximized
// 1: Fullscreen gets maximized
ACTION_WINDOW_UNDOCK_MAX = 390;
// User tried to dock an unresizable app.
ACTION_WINDOW_DOCK_UNRESIZABLE = 391;
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}

View File

@@ -8792,6 +8792,7 @@ public final class ActivityManagerService extends ActivityManagerNative
rti.bounds = new Rect(tr.mBounds);
}
rti.isDockable = tr.canGoInDockedStack();
rti.resizeMode = tr.mResizeMode;
ActivityRecord base = null;
ActivityRecord top = null;

View File

@@ -4776,6 +4776,7 @@ final class ActivityStack {
ci.numActivities = numActivities;
ci.numRunning = numRunning;
ci.isDockable = task.canGoInDockedStack();
ci.resizeMode = task.mResizeMode;
list.add(ci);
}
}