Merge "Update the split screen APIs used by the launcher" into sc-dev

This commit is contained in:
Winson Chung
2021-03-05 04:25:11 +00:00
committed by Android (Google) Code Review
9 changed files with 70 additions and 43 deletions

View File

@@ -234,8 +234,8 @@ public class DragAndDropPolicy {
final UserHandle user = intent.getParcelableExtra(EXTRA_USER);
mStarter.startShortcut(packageName, id, stage, position, opts, user);
} else {
mStarter.startIntent(intent.getParcelableExtra(EXTRA_PENDING_INTENT), stage, position,
opts);
mStarter.startIntent(intent.getParcelableExtra(EXTRA_PENDING_INTENT),
mContext, null, stage, position, opts);
}
}
@@ -295,7 +295,8 @@ public class DragAndDropPolicy {
@Nullable Bundle options);
void startShortcut(String packageName, String shortcutId, @StageType int stage,
@StagePosition int position, @Nullable Bundle options, UserHandle user);
void startIntent(PendingIntent intent, @StageType int stage, @StagePosition int position,
void startIntent(PendingIntent intent, Context context, Intent fillInIntent,
@StageType int stage, @StagePosition int position,
@Nullable Bundle options);
void enterSplitScreen(int taskId, boolean leftOrTop);
void exitSplitScreen();
@@ -336,10 +337,11 @@ public class DragAndDropPolicy {
}
@Override
public void startIntent(PendingIntent intent, int stage, int position,
public void startIntent(PendingIntent intent, Context context,
@Nullable Intent fillInIntent, int stage, int position,
@Nullable Bundle options) {
try {
intent.send(null, 0, null, null, null, null, options);
intent.send(mContext, 0, fillInIntent, null, null, null, options);
} catch (PendingIntent.CanceledException e) {
Slog.e(TAG, "Failed to launch activity", e);
}

View File

@@ -19,18 +19,17 @@ package com.android.wm.shell.splitscreen;
import android.annotation.IntDef;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
import java.io.PrintWriter;
/**
* Interface to engage split-screen feature.
* TODO: Figure out which of these are actually needed outside of the Shell
@@ -87,7 +86,7 @@ public interface SplitScreen extends DragAndDropPolicy.Starter {
/** Callback interface for listening to changes in a split-screen stage. */
interface SplitScreenListener {
void onStagePositionChanged(@StageType int stage, @StagePosition int position);
void onTaskStageChanged(int taskId, @StageType int stage);
void onTaskStageChanged(int taskId, @StageType int stage, boolean visible);
}
/** @return {@code true} if split-screen is currently visible. */
@@ -118,6 +117,7 @@ public interface SplitScreen extends DragAndDropPolicy.Starter {
@StageType int stage, @StagePosition int position, @Nullable Bundle options);
void startShortcut(String packageName, String shortcutId, @StageType int stage,
@StagePosition int position, @Nullable Bundle options, UserHandle user);
void startIntent(PendingIntent intent,
@StageType int stage, @StagePosition int position, @Nullable Bundle options);
void startIntent(PendingIntent intent, Context context,
@Nullable Intent fillInIntent, @StageType int stage,
@StagePosition int position, @Nullable Bundle options);
}

View File

@@ -30,6 +30,7 @@ import android.app.ActivityTaskManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.graphics.Rect;
import android.os.Bundle;
@@ -171,12 +172,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter {
}
}
public void startIntent(PendingIntent intent, @SplitScreen.StageType int stage,
public void startIntent(PendingIntent intent, Context context,
Intent fillInIntent, @SplitScreen.StageType int stage,
@SplitScreen.StagePosition int position, @Nullable Bundle options) {
options = resolveStartStage(stage, position, options);
try {
intent.send(null, 0, null, null, null, null, options);
intent.send(context, 0, fillInIntent, null, null, null, options);
} catch (PendingIntent.CanceledException e) {
Slog.e(TAG, "Failed to launch activity", e);
}
@@ -348,10 +350,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter {
}
@Override
public void startIntent(PendingIntent intent, int stage, int position,
@Nullable Bundle options) {
public void startIntent(PendingIntent intent, Context context, Intent fillInIntent,
int stage, int position, @Nullable Bundle options) {
mMainExecutor.execute(() -> {
SplitScreenController.this.startIntent(intent, stage, position, options);
SplitScreenController.this.startIntent(intent, context, fillInIntent, stage,
position, options);
});
}
}

View File

@@ -225,7 +225,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
}
private void onStageChildTaskStatusChanged(
StageListenerImpl stageListener, int taskId, boolean present) {
StageListenerImpl stageListener, int taskId, boolean present, boolean visible) {
int stage;
if (present) {
@@ -236,7 +236,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
}
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onTaskStageChanged(taskId, stage);
mListeners.get(i).onTaskStageChanged(taskId, stage, visible);
}
}
@@ -495,8 +495,8 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
}
@Override
public void onChildTaskStatusChanged(int taskId, boolean present) {
StageCoordinator.this.onStageChildTaskStatusChanged(this, taskId, present);
public void onChildTaskStatusChanged(int taskId, boolean present, boolean visible) {
StageCoordinator.this.onStageChildTaskStatusChanged(this, taskId, present, visible);
}
@Override

View File

@@ -58,7 +58,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
public interface StageListenerCallbacks {
void onRootTaskAppeared();
void onStatusChanged(boolean visible, boolean hasChildren);
void onChildTaskStatusChanged(int taskId, boolean present);
void onChildTaskStatusChanged(int taskId, boolean present, boolean visible);
void onRootTaskVanished();
}
private final StageListenerCallbacks mCallbacks;
@@ -88,7 +88,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
mChildrenLeashes.put(taskId, leash);
mChildrenTaskInfo.put(taskId, taskInfo);
updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
mCallbacks.onChildTaskStatusChanged(taskId, true /* present */);
mCallbacks.onChildTaskStatusChanged(taskId, true /* present */, taskInfo.isVisible);
} else {
throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
+ "\n mRootTaskInfo: " + mRootTaskInfo);
@@ -105,6 +105,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
updateChildTaskSurface(
taskInfo, mChildrenLeashes.get(taskInfo.taskId), false /* firstAppeared */);
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
taskInfo.isVisible);
} else {
throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
+ "\n mRootTaskInfo: " + mRootTaskInfo);
@@ -123,7 +125,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
mChildrenTaskInfo.remove(taskId);
mChildrenLeashes.remove(taskId);
sendStatusChanged();
mCallbacks.onChildTaskStatusChanged(taskId, false /* present */);
mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible);
} else {
throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
+ "\n mRootTaskInfo: " + mRootTaskInfo);
@@ -152,7 +154,9 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
void onSplitScreenListenerRegistered(SplitScreen.SplitScreenListener listener,
@SplitScreen.StageType int stage) {
for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
listener.onTaskStageChanged(mChildrenTaskInfo.keyAt(i), stage);
int taskId = mChildrenTaskInfo.keyAt(i);
listener.onTaskStageChanged(taskId, stage,
mChildrenTaskInfo.get(taskId).isVisible);
}
}

View File

@@ -205,7 +205,7 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -217,12 +217,12 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -234,12 +234,12 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -251,7 +251,7 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -263,7 +263,7 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -276,13 +276,13 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -295,13 +295,13 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
verify(mSplitScreenStarter).startIntent(any(),
verify(mSplitScreenStarter).startIntent(any(), any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}

View File

@@ -21,5 +21,5 @@ package com.android.systemui.shared.recents;
*/
oneway interface ISplitScreenListener {
void onStagePositionChanged(int stage, int position);
void onTaskStageChanged(int taskId, int stage);
}
void onTaskStageChanged(int taskId, int stage, boolean visible);
}

View File

@@ -19,6 +19,7 @@ package com.android.systemui.shared.recents;
import android.app.PendingIntent;
import android.app.PictureInPictureParams;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Insets;
@@ -34,7 +35,7 @@ import com.android.systemui.shared.system.RemoteTransitionCompat;
/**
* Temporary callbacks into SystemUI.
* Next id = 30
* Next id = 43
*/
interface ISystemUiProxy {
@@ -251,5 +252,7 @@ interface ISystemUiProxy {
void startShortcut(in String packageName, in String shortcutId, in int stage, in int position,
in Bundle options, in UserHandle user) = 40;
void startIntent(
in PendingIntent intent, in int stage, in int position, in Bundle options) = 41;
in PendingIntent intent, in Intent fillInIntent, in int stage, in int position,
in Bundle options) = 41;
void removeFromSideStage(in int taskId) = 42;
}

View File

@@ -662,14 +662,29 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
@Override
public void startIntent(PendingIntent intent, int stage, int position, Bundle options) {
public void startIntent(PendingIntent intent, Intent fillInIntent,
int stage, int position, Bundle options) {
if (!verifyCaller("startIntent")) {
return;
}
final long token = Binder.clearCallingIdentity();
try {
mSplitScreenOptional.ifPresent(s ->
s.startIntent(intent, stage, position, options));
s.startIntent(intent, mContext, fillInIntent, stage, position, options));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public void removeFromSideStage(int taskId) {
if (!verifyCaller("removeFromSideStage")) {
return;
}
final long token = Binder.clearCallingIdentity();
try {
mSplitScreenOptional.ifPresent(
s -> s.removeFromSideStage(taskId));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -789,10 +804,10 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
@Override
public void onTaskStageChanged(int taskId, int stage) {
public void onTaskStageChanged(int taskId, int stage, boolean visible) {
try {
if (mISplitScreenListener != null) {
mISplitScreenListener.onTaskStageChanged(taskId, stage);
mISplitScreenListener.onTaskStageChanged(taskId, stage, visible);
}
} catch (RemoteException e) {
Log.e(TAG_OPS, "onTaskStageChanged", e);