Merge "Add logging for splitscreen" into sc-v2-dev

This commit is contained in:
Winson Chung
2021-08-18 16:11:16 +00:00
committed by Android (Google) Code Review
13 changed files with 494 additions and 41 deletions

View File

@@ -158,6 +158,15 @@ public final class SplitLayout {
return mDividePosition; return mDividePosition;
} }
/**
* Returns the divider position as a fraction from 0 to 1.
*/
public float getDividerPositionAsFraction() {
return Math.min(1f, Math.max(0f, isLandscape()
? (float) ((mBounds1.right + mBounds2.left) / 2f) / mBounds2.right
: (float) ((mBounds1.bottom + mBounds2.top) / 2f) / mBounds2.bottom));
}
/** Applies new configuration, returns {@code false} if there's no effect to the layout. */ /** Applies new configuration, returns {@code false} if there's no effect to the layout. */
public boolean updateConfiguration(Configuration configuration) { public boolean updateConfiguration(Configuration configuration) {
boolean affectsLayout = false; boolean affectsLayout = false;
@@ -342,6 +351,13 @@ public final class SplitLayout {
return bounds.width() > bounds.height(); return bounds.width() > bounds.height();
} }
/**
* Return if this layout is landscape.
*/
public boolean isLandscape() {
return isLandscape(mRootBounds);
}
/** Apply recorded surface layout to the {@link SurfaceControl.Transaction}. */ /** Apply recorded surface layout to the {@link SurfaceControl.Transaction}. */
public void applySurfaceChanges(SurfaceControl.Transaction t, SurfaceControl leash1, public void applySurfaceChanges(SurfaceControl.Transaction t, SurfaceControl leash1,
SurfaceControl leash2, SurfaceControl dimLayer1, SurfaceControl dimLayer2) { SurfaceControl leash2, SurfaceControl dimLayer1, SurfaceControl dimLayer2) {

View File

@@ -49,6 +49,7 @@ import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger;
import com.android.internal.protolog.common.ProtoLog; import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R; import com.android.wm.shell.R;
@@ -180,11 +181,11 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
Slog.w(TAG, "Unexpected drag start during an active drag"); Slog.w(TAG, "Unexpected drag start during an active drag");
return false; return false;
} }
InstanceId loggerSessionId = mLogger.logStart(event);
pd.activeDragCount++; pd.activeDragCount++;
pd.dragLayout.prepare(mDisplayController.getDisplayLayout(displayId), pd.dragLayout.prepare(mDisplayController.getDisplayLayout(displayId),
event.getClipData()); event.getClipData(), loggerSessionId);
setDropTargetWindowVisibility(pd, View.VISIBLE); setDropTargetWindowVisibility(pd, View.VISIBLE);
mLogger.logStart(event);
break; break;
case ACTION_DRAG_ENTERED: case ACTION_DRAG_ENTERED:
pd.dragLayout.show(); pd.dragLayout.show();

View File

@@ -51,7 +51,7 @@ public class DragAndDropEventLogger {
/** /**
* Logs the start of a drag. * Logs the start of a drag.
*/ */
public void logStart(DragEvent event) { public InstanceId logStart(DragEvent event) {
final ClipDescription description = event.getClipDescription(); final ClipDescription description = event.getClipDescription();
final ClipData data = event.getClipData(); final ClipData data = event.getClipData();
final ClipData.Item item = data.getItemAt(0); final ClipData.Item item = data.getItemAt(0);
@@ -64,6 +64,7 @@ public class DragAndDropEventLogger {
mUiEventLogger.logWithInstanceId(getStartEnum(description), mUiEventLogger.logWithInstanceId(getStartEnum(description),
mActivityInfo.applicationInfo.uid, mActivityInfo.applicationInfo.uid,
mActivityInfo.applicationInfo.packageName, mInstanceId); mActivityInfo.applicationInfo.packageName, mInstanceId);
return mInstanceId;
} }
/** /**

View File

@@ -63,6 +63,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition; import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.splitscreen.SplitScreen.StageType;
@@ -86,6 +87,7 @@ public class DragAndDropPolicy {
private final SplitScreenController mSplitScreen; private final SplitScreenController mSplitScreen;
private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>(); private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
private InstanceId mLoggerSessionId;
private DragSession mSession; private DragSession mSession;
public DragAndDropPolicy(Context context, SplitScreenController splitScreen) { public DragAndDropPolicy(Context context, SplitScreenController splitScreen) {
@@ -104,7 +106,8 @@ public class DragAndDropPolicy {
/** /**
* Starts a new drag session with the given initial drag data. * Starts a new drag session with the given initial drag data.
*/ */
void start(DisplayLayout displayLayout, ClipData data) { void start(DisplayLayout displayLayout, ClipData data, InstanceId loggerSessionId) {
mLoggerSessionId = loggerSessionId;
mSession = new DragSession(mContext, mActivityTaskManager, displayLayout, data); mSession = new DragSession(mContext, mActivityTaskManager, displayLayout, data);
// TODO(b/169894807): Also update the session data with task stack changes // TODO(b/169894807): Also update the session data with task stack changes
mSession.update(); mSession.update();
@@ -207,6 +210,8 @@ public class DragAndDropPolicy {
// Launch in the side stage if we are not in split-screen already. // Launch in the side stage if we are not in split-screen already.
stage = STAGE_TYPE_SIDE; stage = STAGE_TYPE_SIDE;
} }
// Add some data for logging splitscreen once it is invoked
mSplitScreen.logOnDroppedToSplit(position, mLoggerSessionId);
} }
final ClipDescription description = data.getDescription(); final ClipDescription description = data.getDescription();
@@ -294,7 +299,12 @@ public class DragAndDropPolicy {
@StageType int stage, @SplitPosition int position, @StageType int stage, @SplitPosition int position,
@Nullable Bundle options); @Nullable Bundle options);
void enterSplitScreen(int taskId, boolean leftOrTop); void enterSplitScreen(int taskId, boolean leftOrTop);
void exitSplitScreen();
/**
* Exits splitscreen, with an associated exit trigger from the SplitscreenUIChanged proto
* for logging.
*/
void exitSplitScreen(int exitTrigger);
} }
/** /**
@@ -347,7 +357,7 @@ public class DragAndDropPolicy {
} }
@Override @Override
public void exitSplitScreen() { public void exitSplitScreen(int exitTrigger) {
throw new UnsupportedOperationException("exitSplitScreen not implemented by starter"); throw new UnsupportedOperationException("exitSplitScreen not implemented by starter");
} }
} }

View File

@@ -38,6 +38,7 @@ import android.view.WindowInsets.Type;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog; import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R; import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.DisplayLayout;
@@ -98,8 +99,9 @@ public class DragLayout extends View {
return mHasDropped; return mHasDropped;
} }
public void prepare(DisplayLayout displayLayout, ClipData initialData) { public void prepare(DisplayLayout displayLayout, ClipData initialData,
mPolicy.start(displayLayout, initialData); InstanceId loggerSessionId) {
mPolicy.start(displayLayout, initialData, loggerSessionId);
mHasDropped = false; mHasDropped = false;
mCurrentTarget = null; mCurrentTarget = null;
} }

View File

@@ -51,6 +51,8 @@ import androidx.annotation.BinderThread;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.android.internal.logging.InstanceId;
import com.android.internal.util.FrameworkStatsLog;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayImeController;
@@ -61,7 +63,6 @@ import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition; import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.draganddrop.DragAndDropPolicy; import com.android.wm.shell.draganddrop.DragAndDropPolicy;
import com.android.wm.shell.splitscreen.ISplitScreenListener;
import com.android.wm.shell.transition.LegacyTransitions; import com.android.wm.shell.transition.LegacyTransitions;
import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions;
@@ -86,6 +87,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
private final DisplayImeController mDisplayImeController; private final DisplayImeController mDisplayImeController;
private final Transitions mTransitions; private final Transitions mTransitions;
private final TransactionPool mTransactionPool; private final TransactionPool mTransactionPool;
private final SplitscreenEventLogger mLogger;
private StageCoordinator mStageCoordinator; private StageCoordinator mStageCoordinator;
@@ -102,6 +104,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
mDisplayImeController = displayImeController; mDisplayImeController = displayImeController;
mTransitions = transitions; mTransitions = transitions;
mTransactionPool = transactionPool; mTransactionPool = transactionPool;
mLogger = new SplitscreenEventLogger();
} }
public SplitScreen asSplitScreen() { public SplitScreen asSplitScreen() {
@@ -123,7 +126,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
// TODO: Multi-display // TODO: Multi-display
mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController, mTransitions, mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController, mTransitions,
mTransactionPool); mTransactionPool, mLogger);
} }
} }
@@ -165,8 +168,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT); leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
} }
public void exitSplitScreen() { public void exitSplitScreen(int exitReason) {
mStageCoordinator.exitSplitScreen(); mStageCoordinator.exitSplitScreen(exitReason);
} }
public void onKeyguardOccludedChanged(boolean occluded) { public void onKeyguardOccludedChanged(boolean occluded) {
@@ -303,6 +306,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()}; return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()};
} }
/**
* Sets drag info to be logged when splitscreen is entered.
*/
public void logOnDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) {
mStageCoordinator.logOnDroppedToSplit(position, dragSessionId);
}
public void dump(@NonNull PrintWriter pw, String prefix) { public void dump(@NonNull PrintWriter pw, String prefix) {
pw.println(prefix + TAG); pw.println(prefix + TAG);
if (mStageCoordinator != null) { if (mStageCoordinator != null) {
@@ -495,7 +505,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
public void exitSplitScreen() { public void exitSplitScreen() {
executeRemoteCallWithTaskPermission(mController, "exitSplitScreen", executeRemoteCallWithTaskPermission(mController, "exitSplitScreen",
(controller) -> { (controller) -> {
controller.exitSplitScreen(); controller.exitSplitScreen(
FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
}); });
} }

View File

@@ -0,0 +1,324 @@
/*
* 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.wm.shell.splitscreen;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__OVERVIEW;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.util.FrameworkStatsLog;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
/**
* Helper class that to log Drag & Drop UIEvents for a single session, see also go/uievent
*/
public class SplitscreenEventLogger {
// Used to generate instance ids for this drag if one is not provided
private final InstanceIdSequence mIdSequence;
// The instance id for the current splitscreen session (from start to end)
private InstanceId mLoggerSessionId;
// Drag info
private @SplitPosition int mDragEnterPosition;
private InstanceId mDragEnterSessionId;
// For deduping async events
private int mLastMainStagePosition = -1;
private int mLastMainStageUid = -1;
private int mLastSideStagePosition = -1;
private int mLastSideStageUid = -1;
private float mLastSplitRatio = -1f;
public SplitscreenEventLogger() {
mIdSequence = new InstanceIdSequence(Integer.MAX_VALUE);
}
/**
* Return whether a splitscreen session has started.
*/
public boolean hasStartedSession() {
return mLoggerSessionId != null;
}
/**
* May be called before logEnter() to indicate that the session was started from a drag.
*/
public void enterRequestedByDrag(@SplitPosition int position, InstanceId dragSessionId) {
mDragEnterPosition = position;
mDragEnterSessionId = dragSessionId;
}
/**
* Logs when the user enters splitscreen.
*/
public void logEnter(float splitRatio,
@SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid,
boolean isLandscape) {
mLoggerSessionId = mIdSequence.newInstanceId();
int enterReason = mDragEnterPosition != SPLIT_POSITION_UNDEFINED
? getDragEnterReasonFromSplitPosition(mDragEnterPosition, isLandscape)
: SPLITSCREEN_UICHANGED__ENTER_REASON__OVERVIEW;
updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
mainStageUid);
updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
sideStageUid);
updateSplitRatioState(splitRatio);
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__ENTER,
enterReason,
0 /* exitReason */,
splitRatio,
mLastMainStagePosition,
mLastMainStageUid,
mLastSideStagePosition,
mLastSideStageUid,
mDragEnterSessionId != null ? mDragEnterSessionId.getId() : 0,
mLoggerSessionId.getId());
}
/**
* Logs when the user exits splitscreen. Only one of the main or side stages should be
* specified to indicate which position was focused as a part of exiting (both can be unset).
*/
public void logExit(int exitReason, @SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
if (mLoggerSessionId == null) {
// Ignore changes until we've started logging the session
return;
}
if ((mainStagePosition != SPLIT_POSITION_UNDEFINED
&& sideStagePosition != SPLIT_POSITION_UNDEFINED)
|| (mainStageUid != 0 && sideStageUid != 0)) {
throw new IllegalArgumentException("Only main or side stage should be set");
}
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__EXIT,
0 /* enterReason */,
exitReason,
0f /* splitRatio */,
getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
mainStageUid,
getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
sideStageUid,
0 /* dragInstanceId */,
mLoggerSessionId.getId());
// Reset states
mLoggerSessionId = null;
mDragEnterPosition = SPLIT_POSITION_UNDEFINED;
mDragEnterSessionId = null;
mLastMainStagePosition = -1;
mLastMainStageUid = -1;
mLastSideStagePosition = -1;
mLastSideStageUid = -1;
}
/**
* Logs when an app in the main stage changes.
*/
public void logMainStageAppChange(@SplitPosition int mainStagePosition, int mainStageUid,
boolean isLandscape) {
if (mLoggerSessionId == null) {
// Ignore changes until we've started logging the session
return;
}
if (!updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition,
isLandscape), mainStageUid)) {
// Ignore if there are no user perceived changes
return;
}
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__APP_CHANGE,
0 /* enterReason */,
0 /* exitReason */,
0f /* splitRatio */,
mLastMainStagePosition,
mLastMainStageUid,
0 /* sideStagePosition */,
0 /* sideStageUid */,
0 /* dragInstanceId */,
mLoggerSessionId.getId());
}
/**
* Logs when an app in the side stage changes.
*/
public void logSideStageAppChange(@SplitPosition int sideStagePosition, int sideStageUid,
boolean isLandscape) {
if (mLoggerSessionId == null) {
// Ignore changes until we've started logging the session
return;
}
if (!updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition,
isLandscape), sideStageUid)) {
// Ignore if there are no user perceived changes
return;
}
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__APP_CHANGE,
0 /* enterReason */,
0 /* exitReason */,
0f /* splitRatio */,
0 /* mainStagePosition */,
0 /* mainStageUid */,
mLastSideStagePosition,
mLastSideStageUid,
0 /* dragInstanceId */,
mLoggerSessionId.getId());
}
/**
* Logs when the splitscreen ratio changes.
*/
public void logResize(float splitRatio) {
if (mLoggerSessionId == null) {
// Ignore changes until we've started logging the session
return;
}
if (splitRatio <= 0f || splitRatio >= 1f) {
// Don't bother reporting resizes that end up dismissing the split, that will be logged
// via the exit event
return;
}
if (!updateSplitRatioState(splitRatio)) {
// Ignore if there are no user perceived changes
return;
}
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__RESIZE,
0 /* enterReason */,
0 /* exitReason */,
mLastSplitRatio,
0 /* mainStagePosition */, 0 /* mainStageUid */,
0 /* sideStagePosition */, 0 /* sideStageUid */,
0 /* dragInstanceId */,
mLoggerSessionId.getId());
}
/**
* Logs when the apps in splitscreen are swapped.
*/
public void logSwap(@SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
if (mLoggerSessionId == null) {
// Ignore changes until we've started logging the session
return;
}
updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
mainStageUid);
updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
sideStageUid);
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__SWAP,
0 /* enterReason */,
0 /* exitReason */,
0f /* splitRatio */,
mLastMainStagePosition,
mLastMainStageUid,
mLastSideStagePosition,
mLastSideStageUid,
0 /* dragInstanceId */,
mLoggerSessionId.getId());
}
private boolean updateMainStageState(int mainStagePosition, int mainStageUid) {
boolean changed = (mLastMainStagePosition != mainStagePosition)
|| (mLastMainStageUid != mainStageUid);
if (!changed) {
return false;
}
mLastMainStagePosition = mainStagePosition;
mLastMainStageUid = mainStageUid;
return true;
}
private boolean updateSideStageState(int sideStagePosition, int sideStageUid) {
boolean changed = (mLastSideStagePosition != sideStagePosition)
|| (mLastSideStageUid != sideStageUid);
if (!changed) {
return false;
}
mLastSideStagePosition = sideStagePosition;
mLastSideStageUid = sideStageUid;
return true;
}
private boolean updateSplitRatioState(float splitRatio) {
boolean changed = Float.compare(mLastSplitRatio, splitRatio) != 0;
if (!changed) {
return false;
}
mLastSplitRatio = splitRatio;
return true;
}
public int getDragEnterReasonFromSplitPosition(@SplitPosition int position,
boolean isLandscape) {
if (isLandscape) {
return position == SPLIT_POSITION_TOP_OR_LEFT
? FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_LEFT
: FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_RIGHT;
} else {
return position == SPLIT_POSITION_TOP_OR_LEFT
? FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_TOP
: FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__DRAG_BOTTOM;
}
}
private int getMainStagePositionFromSplitPosition(@SplitPosition int position,
boolean isLandscape) {
if (position == SPLIT_POSITION_UNDEFINED) {
return 0;
}
if (isLandscape) {
return position == SPLIT_POSITION_TOP_OR_LEFT
? FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__LEFT
: FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__RIGHT;
} else {
return position == SPLIT_POSITION_TOP_OR_LEFT
? FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__TOP
: FrameworkStatsLog.SPLITSCREEN_UICHANGED__MAIN_STAGE_POSITION__BOTTOM;
}
}
private int getSideStagePositionFromSplitPosition(@SplitPosition int position,
boolean isLandscape) {
if (position == SPLIT_POSITION_UNDEFINED) {
return 0;
}
if (isLandscape) {
return position == SPLIT_POSITION_TOP_OR_LEFT
? FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__LEFT
: FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__RIGHT;
} else {
return position == SPLIT_POSITION_TOP_OR_LEFT
? FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__TOP
: FrameworkStatsLog.SPLITSCREEN_UICHANGED__SIDE_STAGE_POSITION__BOTTOM;
}
}
}

View File

@@ -26,6 +26,12 @@ import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString; import static android.view.WindowManager.transitTypeToString;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
@@ -73,6 +79,7 @@ import android.window.WindowContainerTransaction;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog; import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTaskOrganizer;
@@ -130,6 +137,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>(); private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>();
private final DisplayImeController mDisplayImeController; private final DisplayImeController mDisplayImeController;
private final SplitScreenTransitions mSplitTransitions; private final SplitScreenTransitions mSplitTransitions;
private final SplitscreenEventLogger mLogger;
private boolean mExitSplitScreenOnHide; private boolean mExitSplitScreenOnHide;
private boolean mKeyguardOccluded; private boolean mKeyguardOccluded;
@@ -156,12 +164,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer, RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
DisplayImeController displayImeController, Transitions transitions, DisplayImeController displayImeController, Transitions transitions,
TransactionPool transactionPool) { TransactionPool transactionPool, SplitscreenEventLogger logger) {
mContext = context; mContext = context;
mDisplayId = displayId; mDisplayId = displayId;
mSyncQueue = syncQueue; mSyncQueue = syncQueue;
mRootTDAOrganizer = rootTDAOrganizer; mRootTDAOrganizer = rootTDAOrganizer;
mTaskOrganizer = taskOrganizer; mTaskOrganizer = taskOrganizer;
mLogger = logger;
mMainStage = new MainStage( mMainStage = new MainStage(
mTaskOrganizer, mTaskOrganizer,
mDisplayId, mDisplayId,
@@ -190,7 +199,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer, RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
MainStage mainStage, SideStage sideStage, DisplayImeController displayImeController, MainStage mainStage, SideStage sideStage, DisplayImeController displayImeController,
SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool) { SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool,
SplitscreenEventLogger logger) {
mContext = context; mContext = context;
mDisplayId = displayId; mDisplayId = displayId;
mSyncQueue = syncQueue; mSyncQueue = syncQueue;
@@ -203,6 +213,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitLayout = splitLayout; mSplitLayout = splitLayout;
mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions, mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
mOnTransitionAnimationComplete); mOnTransitionAnimationComplete);
mLogger = logger;
transitions.addHandler(this); transitions.addHandler(this);
} }
@@ -450,19 +461,20 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
void onKeyguardVisibilityChanged(boolean showing) { void onKeyguardVisibilityChanged(boolean showing) {
if (!showing && mMainStage.isActive() if (!showing && mMainStage.isActive()
&& mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) { && mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) {
exitSplitScreen(mTopStageAfterFoldDismiss == STAGE_TYPE_MAIN ? mMainStage : mSideStage); exitSplitScreen(mTopStageAfterFoldDismiss == STAGE_TYPE_MAIN ? mMainStage : mSideStage,
SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED);
} }
} }
void exitSplitScreen() { void exitSplitScreen(int exitReason) {
exitSplitScreen(null /* childrenToTop */); exitSplitScreen(null /* childrenToTop */, exitReason);
} }
void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) { void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
mExitSplitScreenOnHide = exitSplitScreenOnHide; mExitSplitScreenOnHide = exitSplitScreenOnHide;
} }
private void exitSplitScreen(StageTaskListener childrenToTop) { private void exitSplitScreen(StageTaskListener childrenToTop, int exitReason) {
final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction wct = new WindowContainerTransaction();
mSideStage.removeAllTasks(wct, childrenToTop == mSideStage); mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
mMainStage.deactivate(wct, childrenToTop == mMainStage); mMainStage.deactivate(wct, childrenToTop == mMainStage);
@@ -470,6 +482,11 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Reset divider position. // Reset divider position.
mSplitLayout.resetDividerPosition(); mSplitLayout.resetDividerPosition();
mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED; mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
if (childrenToTop != null) {
logExitToStage(exitReason, childrenToTop == mMainStage);
} else {
logExit(exitReason);
}
} }
/** /**
@@ -522,9 +539,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
} }
private void onStageChildTaskStatusChanged( private void onStageChildTaskStatusChanged(StageListenerImpl stageListener, int taskId,
StageListenerImpl stageListener, int taskId, boolean present, boolean visible) { boolean present, boolean visible) {
int stage; int stage;
if (present) { if (present) {
stage = stageListener == mSideStageListener ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN; stage = stageListener == mSideStageListener ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN;
@@ -532,6 +548,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// No longer on any stage // No longer on any stage
stage = STAGE_TYPE_UNDEFINED; stage = STAGE_TYPE_UNDEFINED;
} }
if (stage == STAGE_TYPE_MAIN) {
mLogger.logMainStageAppChange(getMainStagePosition(), mMainStage.getTopChildTaskUid(),
mSplitLayout.isLandscape());
} else {
mLogger.logSideStageAppChange(getSideStagePosition(), mSideStage.getTopChildTaskUid(),
mSplitLayout.isLandscape());
}
for (int i = mListeners.size() - 1; i >= 0; --i) { for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onTaskStageChanged(taskId, stage, visible); mListeners.get(i).onTaskStageChanged(taskId, stage, visible);
@@ -598,7 +621,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Don't dismiss staged split when both stages are not visible due to sleeping display, // Don't dismiss staged split when both stages are not visible due to sleeping display,
// like the cases keyguard showing or screen off. // like the cases keyguard showing or screen off.
|| (!mMainStage.mRootTaskInfo.isSleeping && !mSideStage.mRootTaskInfo.isSleeping)) { || (!mMainStage.mRootTaskInfo.isSleeping && !mSideStage.mRootTaskInfo.isSleeping)) {
exitSplitScreen(); exitSplitScreen(SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
} }
} else if (mKeyguardOccluded) { } else if (mKeyguardOccluded) {
// At least one of the stages is visible while keyguard occluded. Dismiss split because // At least one of the stages is visible while keyguard occluded. Dismiss split because
@@ -606,7 +629,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// task contains show-when-locked activity remains on top after split dismissed. // task contains show-when-locked activity remains on top after split dismissed.
final StageTaskListener toTop = final StageTaskListener toTop =
mainStageVisible ? mMainStage : (sideStageVisible ? mSideStage : null); mainStageVisible ? mMainStage : (sideStageVisible ? mSideStage : null);
exitSplitScreen(toTop); exitSplitScreen(toTop, SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP);
} }
// When both stage's visibility changed to visible, main stage might receives visibility // When both stage's visibility changed to visible, main stage might receives visibility
@@ -683,17 +706,16 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
private void onStageHasChildrenChanged(StageListenerImpl stageListener) { private void onStageHasChildrenChanged(StageListenerImpl stageListener) {
final boolean hasChildren = stageListener.mHasChildren; final boolean hasChildren = stageListener.mHasChildren;
final boolean isSideStage = stageListener == mSideStageListener; final boolean isSideStage = stageListener == mSideStageListener;
if (!hasChildren) { if (!hasChildren) {
if (isSideStage && mMainStageListener.mVisible) { if (isSideStage && mMainStageListener.mVisible) {
// Exit to main stage if side stage no longer has children. // Exit to main stage if side stage no longer has children.
exitSplitScreen(mMainStage); exitSplitScreen(mMainStage, SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED);
} else if (!isSideStage && mSideStageListener.mVisible) { } else if (!isSideStage && mSideStageListener.mVisible) {
// Exit to side stage if main stage no longer has children. // Exit to side stage if main stage no longer has children.
exitSplitScreen(mSideStage); exitSplitScreen(mSideStage, SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED);
} }
} else if (isSideStage) { } else if (isSideStage) {
final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -702,6 +724,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSideStage.setBounds(getSideStageBounds(), wct); mSideStage.setBounds(getSideStageBounds(), wct);
mTaskOrganizer.applyTransaction(wct); mTaskOrganizer.applyTransaction(wct);
} }
if (!mLogger.hasStartedSession() && mMainStageListener.mHasChildren
&& mSideStageListener.mHasChildren) {
mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
getMainStagePosition(), mMainStage.getTopChildTaskUid(),
getSideStagePosition(), mSideStage.getTopChildTaskUid(),
mSplitLayout.isLandscape());
}
} }
@VisibleForTesting @VisibleForTesting
@@ -720,13 +749,17 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
onSnappedToDismissTransition(mainStageToTop); onSnappedToDismissTransition(mainStageToTop);
return; return;
} }
exitSplitScreen(mainStageToTop ? mMainStage : mSideStage); exitSplitScreen(mainStageToTop ? mMainStage : mSideStage,
SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER);
} }
@Override @Override
public void onDoubleTappedDivider() { public void onDoubleTappedDivider() {
setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT, null /* wct */); ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT, null /* wct */);
mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(),
getSideStagePosition(), mSideStage.getTopChildTaskUid(),
mSplitLayout.isLandscape());
} }
@Override @Override
@@ -740,6 +773,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
updateWindowBounds(layout, wct); updateWindowBounds(layout, wct);
mSyncQueue.queue(wct); mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t)); mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
mLogger.logResize(mSplitLayout.getDividerPositionAsFraction());
} }
/** /**
@@ -1139,6 +1173,36 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainStageListener.mHasChildren = mSideStageListener.mHasChildren = visible; mMainStageListener.mHasChildren = mSideStageListener.mHasChildren = visible;
} }
/**
* Sets drag info to be logged when splitscreen is next entered.
*/
public void logOnDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) {
mLogger.enterRequestedByDrag(position, dragSessionId);
}
/**
* Logs the exit of splitscreen.
*/
private void logExit(int exitReason) {
mLogger.logExit(exitReason,
SPLIT_POSITION_UNDEFINED, 0 /* mainStageUid */,
SPLIT_POSITION_UNDEFINED, 0 /* sideStageUid */,
mSplitLayout.isLandscape());
}
/**
* Logs the exit of splitscreen to a specific stage. This must be called before the exit is
* executed.
*/
private void logExitToStage(int exitReason, boolean toMainStage) {
mLogger.logExit(exitReason,
toMainStage ? getMainStagePosition() : SPLIT_POSITION_UNDEFINED,
toMainStage ? mMainStage.getTopChildTaskUid() : 0 /* mainStageUid */,
!toMainStage ? getSideStagePosition() : SPLIT_POSITION_UNDEFINED,
!toMainStage ? mSideStage.getTopChildTaskUid() : 0 /* sideStageUid */,
mSplitLayout.isLandscape());
}
class StageListenerImpl implements StageTaskListener.StageListenerCallbacks { class StageListenerImpl implements StageTaskListener.StageListenerCallbacks {
boolean mHasRootTask = false; boolean mHasRootTask = false;
boolean mVisible = false; boolean mVisible = false;
@@ -1178,7 +1242,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override @Override
public void onNoLongerSupportMultiWindow() { public void onNoLongerSupportMultiWindow() {
if (mMainStage.isActive()) { if (mMainStage.isActive()) {
StageCoordinator.this.exitSplitScreen(); StageCoordinator.this.exitSplitScreen(
SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW);
} }
} }

View File

@@ -97,6 +97,20 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
return mChildrenTaskInfo.contains(taskId); return mChildrenTaskInfo.contains(taskId);
} }
/**
* Returns the top activity uid for the top child task.
*/
int getTopChildTaskUid() {
for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo info = mChildrenTaskInfo.valueAt(i);
if (info.topActivityInfo == null) {
continue;
}
return info.topActivityInfo.applicationInfo.uid;
}
return 0;
}
/** @return {@code true} if this listener contains the currently focused task. */ /** @return {@code true} if this listener contains the currently focused task. */
boolean isFocused() { boolean isFocused() {
if (mRootTaskInfo.isFocused) return true; if (mRootTaskInfo.isFocused) return true;

View File

@@ -65,6 +65,7 @@ import android.view.DisplayInfo;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.internal.logging.InstanceId;
import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.draganddrop.DragAndDropPolicy.Target; import com.android.wm.shell.draganddrop.DragAndDropPolicy.Target;
import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -96,6 +97,9 @@ public class DragAndDropPolicyTest {
@Mock @Mock
private SplitScreenController mSplitScreenStarter; private SplitScreenController mSplitScreenStarter;
@Mock
private InstanceId mLoggerSessionId;
private DisplayLayout mLandscapeDisplayLayout; private DisplayLayout mLandscapeDisplayLayout;
private DisplayLayout mPortraitDisplayLayout; private DisplayLayout mPortraitDisplayLayout;
private Insets mInsets; private Insets mInsets;
@@ -201,7 +205,7 @@ public class DragAndDropPolicyTest {
@Test @Test
public void testDragAppOverFullscreenHome_expectOnlyFullscreenTarget() { public void testDragAppOverFullscreenHome_expectOnlyFullscreenTarget() {
setRunningTask(mHomeTask); setRunningTask(mHomeTask);
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData); mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes( ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN); mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
@@ -213,7 +217,7 @@ public class DragAndDropPolicyTest {
@Test @Test
public void testDragAppOverFullscreenApp_expectSplitScreenTargets() { public void testDragAppOverFullscreenApp_expectSplitScreenTargets() {
setRunningTask(mFullscreenAppTask); setRunningTask(mFullscreenAppTask);
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData); mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes( ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
@@ -230,7 +234,7 @@ public class DragAndDropPolicyTest {
@Test @Test
public void testDragAppOverFullscreenAppPhone_expectVerticalSplitScreenTargets() { public void testDragAppOverFullscreenAppPhone_expectVerticalSplitScreenTargets() {
setRunningTask(mFullscreenAppTask); setRunningTask(mFullscreenAppTask);
mPolicy.start(mPortraitDisplayLayout, mActivityClipData); mPolicy.start(mPortraitDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes( ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM); mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
@@ -248,7 +252,7 @@ public class DragAndDropPolicyTest {
public void testDragAppOverSplitApp_expectSplitTargets_DropLeft() { public void testDragAppOverSplitApp_expectSplitTargets_DropLeft() {
setInSplitScreen(true); setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask); setRunningTask(mSplitPrimaryAppTask);
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData); mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes( ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
@@ -261,7 +265,7 @@ public class DragAndDropPolicyTest {
public void testDragAppOverSplitApp_expectSplitTargets_DropRight() { public void testDragAppOverSplitApp_expectSplitTargets_DropRight() {
setInSplitScreen(true); setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask); setRunningTask(mSplitPrimaryAppTask);
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData); mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes( ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
@@ -274,7 +278,7 @@ public class DragAndDropPolicyTest {
public void testDragAppOverSplitAppPhone_expectVerticalSplitTargets_DropTop() { public void testDragAppOverSplitAppPhone_expectVerticalSplitTargets_DropTop() {
setInSplitScreen(true); setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask); setRunningTask(mSplitPrimaryAppTask);
mPolicy.start(mPortraitDisplayLayout, mActivityClipData); mPolicy.start(mPortraitDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes( ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM); mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
@@ -287,7 +291,7 @@ public class DragAndDropPolicyTest {
public void testDragAppOverSplitAppPhone_expectVerticalSplitTargets_DropBottom() { public void testDragAppOverSplitAppPhone_expectVerticalSplitTargets_DropBottom() {
setInSplitScreen(true); setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask); setRunningTask(mSplitPrimaryAppTask);
mPolicy.start(mPortraitDisplayLayout, mActivityClipData); mPolicy.start(mPortraitDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes( ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM); mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
@@ -299,7 +303,7 @@ public class DragAndDropPolicyTest {
@Test @Test
public void testTargetHitRects() { public void testTargetHitRects() {
setRunningTask(mFullscreenAppTask); setRunningTask(mFullscreenAppTask);
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData); mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
ArrayList<Target> targets = mPolicy.getTargets(mInsets); ArrayList<Target> targets = mPolicy.getTargets(mInsets);
for (Target t : targets) { for (Target t : targets) {
assertTrue(mPolicy.getTargetAtLocation(t.hitRegion.left, t.hitRegion.top) == t); assertTrue(mPolicy.getTargetAtLocation(t.hitRegion.left, t.hitRegion.top) == t);

View File

@@ -65,9 +65,10 @@ public class SplitTestUtils {
TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer, RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
MainStage mainStage, SideStage sideStage, DisplayImeController imeController, MainStage mainStage, SideStage sideStage, DisplayImeController imeController,
SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool) { SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool,
SplitscreenEventLogger logger) {
super(context, displayId, syncQueue, rootTDAOrganizer, taskOrganizer, mainStage, super(context, displayId, syncQueue, rootTDAOrganizer, taskOrganizer, mainStage,
sideStage, imeController, splitLayout, transitions, transactionPool); sideStage, imeController, splitLayout, transitions, transactionPool, logger);
// Prepare default TaskDisplayArea for testing. // Prepare default TaskDisplayArea for testing.
mDisplayAreaInfo = new DisplayAreaInfo( mDisplayAreaInfo = new DisplayAreaInfo(

View File

@@ -82,6 +82,7 @@ public class SplitTransitionTests extends ShellTestCase {
@Mock private TransactionPool mTransactionPool; @Mock private TransactionPool mTransactionPool;
@Mock private Transitions mTransitions; @Mock private Transitions mTransitions;
@Mock private SurfaceSession mSurfaceSession; @Mock private SurfaceSession mSurfaceSession;
@Mock private SplitscreenEventLogger mLogger;
private SplitLayout mSplitLayout; private SplitLayout mSplitLayout;
private MainStage mMainStage; private MainStage mMainStage;
private SideStage mSideStage; private SideStage mSideStage;
@@ -107,7 +108,8 @@ public class SplitTransitionTests extends ShellTestCase {
mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface()); mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY, mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage, mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage,
mDisplayImeController, mSplitLayout, mTransitions, mTransactionPool); mDisplayImeController, mSplitLayout, mTransitions, mTransactionPool,
mLogger);
mSplitScreenTransitions = mStageCoordinator.getSplitTransitions(); mSplitScreenTransitions = mStageCoordinator.getSplitTransitions();
doAnswer((Answer<IBinder>) invocation -> mock(IBinder.class)) doAnswer((Answer<IBinder>) invocation -> mock(IBinder.class))
.when(mTransitions).startTransition(anyInt(), any(), any()); .when(mTransitions).startTransition(anyInt(), any(), any());

View File

@@ -59,6 +59,7 @@ public class StageCoordinatorTests extends ShellTestCase {
@Mock private DisplayImeController mDisplayImeController; @Mock private DisplayImeController mDisplayImeController;
@Mock private Transitions mTransitions; @Mock private Transitions mTransitions;
@Mock private TransactionPool mTransactionPool; @Mock private TransactionPool mTransactionPool;
@Mock private SplitscreenEventLogger mLogger;
private StageCoordinator mStageCoordinator; private StageCoordinator mStageCoordinator;
@Before @Before
@@ -66,7 +67,8 @@ public class StageCoordinatorTests extends ShellTestCase {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY, mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage, mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage,
mDisplayImeController, null /* splitLayout */, mTransitions, mTransactionPool); mDisplayImeController, null /* splitLayout */, mTransitions, mTransactionPool,
mLogger);
} }
@Test @Test