Merge "Fix transitions in the background when launching something in TaskView" into sc-dev
This commit is contained in:
@@ -118,15 +118,15 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
*
|
*
|
||||||
* @param shortcut the shortcut used to launch the activity.
|
* @param shortcut the shortcut used to launch the activity.
|
||||||
* @param options options for the activity.
|
* @param options options for the activity.
|
||||||
* @param sourceBounds the rect containing the source bounds of the clicked icon to open
|
* @param launchBounds the bounds (window size and position) that the activity should be
|
||||||
* this shortcut.
|
* launched in, in pixels and in screen coordinates.
|
||||||
*/
|
*/
|
||||||
public void startShortcutActivity(@NonNull ShortcutInfo shortcut,
|
public void startShortcutActivity(@NonNull ShortcutInfo shortcut,
|
||||||
@NonNull ActivityOptions options, @Nullable Rect sourceBounds) {
|
@NonNull ActivityOptions options, @Nullable Rect launchBounds) {
|
||||||
prepareActivityOptions(options);
|
prepareActivityOptions(options, launchBounds);
|
||||||
LauncherApps service = mContext.getSystemService(LauncherApps.class);
|
LauncherApps service = mContext.getSystemService(LauncherApps.class);
|
||||||
try {
|
try {
|
||||||
service.startShortcut(shortcut, sourceBounds, options.toBundle());
|
service.startShortcut(shortcut, null /* sourceBounds */, options.toBundle());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -138,10 +138,12 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
* @param pendingIntent Intent used to launch an activity.
|
* @param pendingIntent Intent used to launch an activity.
|
||||||
* @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}
|
* @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}
|
||||||
* @param options options for the activity.
|
* @param options options for the activity.
|
||||||
|
* @param launchBounds the bounds (window size and position) that the activity should be
|
||||||
|
* launched in, in pixels and in screen coordinates.
|
||||||
*/
|
*/
|
||||||
public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
|
public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
|
||||||
@NonNull ActivityOptions options) {
|
@NonNull ActivityOptions options, @Nullable Rect launchBounds) {
|
||||||
prepareActivityOptions(options);
|
prepareActivityOptions(options, launchBounds);
|
||||||
try {
|
try {
|
||||||
pendingIntent.send(mContext, 0 /* code */, fillInIntent,
|
pendingIntent.send(mContext, 0 /* code */, fillInIntent,
|
||||||
null /* onFinished */, null /* handler */, null /* requiredPermission */,
|
null /* onFinished */, null /* handler */, null /* requiredPermission */,
|
||||||
@@ -151,11 +153,12 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareActivityOptions(ActivityOptions options) {
|
private void prepareActivityOptions(ActivityOptions options, Rect launchBounds) {
|
||||||
final Binder launchCookie = new Binder();
|
final Binder launchCookie = new Binder();
|
||||||
mShellExecutor.execute(() -> {
|
mShellExecutor.execute(() -> {
|
||||||
mTaskOrganizer.setPendingLaunchCookieListener(launchCookie, this);
|
mTaskOrganizer.setPendingLaunchCookieListener(launchCookie, this);
|
||||||
});
|
});
|
||||||
|
options.setLaunchBounds(launchBounds);
|
||||||
options.setLaunchCookie(launchCookie);
|
options.setLaunchCookie(launchCookie);
|
||||||
options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
|
options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
|
||||||
options.setRemoveWithTaskOrganizer(true);
|
options.setRemoveWithTaskOrganizer(true);
|
||||||
|
|||||||
@@ -153,6 +153,9 @@ public class BubbleExpandedView extends LinearLayout {
|
|||||||
ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(),
|
ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(),
|
||||||
0 /* enterResId */, 0 /* exitResId */);
|
0 /* enterResId */, 0 /* exitResId */);
|
||||||
|
|
||||||
|
Rect launchBounds = new Rect();
|
||||||
|
mTaskView.getBoundsOnScreen(launchBounds);
|
||||||
|
|
||||||
// TODO: I notice inconsistencies in lifecycle
|
// TODO: I notice inconsistencies in lifecycle
|
||||||
// Post to keep the lifecycle normal
|
// Post to keep the lifecycle normal
|
||||||
post(() -> {
|
post(() -> {
|
||||||
@@ -166,7 +169,7 @@ public class BubbleExpandedView extends LinearLayout {
|
|||||||
if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
|
if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
|
||||||
options.setApplyActivityFlagsForBubbles(true);
|
options.setApplyActivityFlagsForBubbles(true);
|
||||||
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
|
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
|
||||||
options, null /* sourceBounds */);
|
options, launchBounds);
|
||||||
} else {
|
} else {
|
||||||
Intent fillInIntent = new Intent();
|
Intent fillInIntent = new Intent();
|
||||||
// Apply flags to make behaviour match documentLaunchMode=always.
|
// Apply flags to make behaviour match documentLaunchMode=always.
|
||||||
@@ -175,7 +178,8 @@ public class BubbleExpandedView extends LinearLayout {
|
|||||||
if (mBubble != null) {
|
if (mBubble != null) {
|
||||||
mBubble.setIntentActive();
|
mBubble.setIntentActive();
|
||||||
}
|
}
|
||||||
mTaskView.startActivity(mPendingIntent, fillInIntent, options);
|
mTaskView.startActivity(mPendingIntent, fillInIntent, options,
|
||||||
|
launchBounds);
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// If there's a runtime exception here then there's something
|
// If there's a runtime exception here then there's something
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import android.app.ActivityManager;
|
|||||||
import android.app.ActivityOptions;
|
import android.app.ActivityOptions;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
@@ -125,7 +126,7 @@ public class TaskViewTest extends ShellTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testStartActivity() {
|
public void testStartActivity() {
|
||||||
ActivityOptions options = ActivityOptions.makeBasic();
|
ActivityOptions options = ActivityOptions.makeBasic();
|
||||||
mTaskView.startActivity(mock(PendingIntent.class), null, options);
|
mTaskView.startActivity(mock(PendingIntent.class), null, options, new Rect(0, 0, 100, 100));
|
||||||
|
|
||||||
verify(mOrganizer).setPendingLaunchCookieListener(any(), eq(mTaskView));
|
verify(mOrganizer).setPendingLaunchCookieListener(any(), eq(mTaskView));
|
||||||
assertThat(options.getLaunchWindowingMode()).isEqualTo(WINDOWING_MODE_MULTI_WINDOW);
|
assertThat(options.getLaunchWindowingMode()).isEqualTo(WINDOWING_MODE_MULTI_WINDOW);
|
||||||
|
|||||||
@@ -1333,6 +1333,7 @@
|
|||||||
<dimen name="controls_setup_title">22sp</dimen>
|
<dimen name="controls_setup_title">22sp</dimen>
|
||||||
<dimen name="controls_setup_subtitle">14sp</dimen>
|
<dimen name="controls_setup_subtitle">14sp</dimen>
|
||||||
<dimen name="controls_setup_vertical_padding">52dp</dimen>
|
<dimen name="controls_setup_vertical_padding">52dp</dimen>
|
||||||
|
<dimen name="controls_detail_dialog_header_height">52dp</dimen>
|
||||||
|
|
||||||
<!-- Home Controls activity view detail panel-->
|
<!-- Home Controls activity view detail panel-->
|
||||||
<dimen name="controls_activity_view_top_offset">100dp</dimen>
|
<dimen name="controls_activity_view_top_offset">100dp</dimen>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.app.PendingIntent
|
|||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.Rect
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
@@ -83,8 +84,9 @@ class DetailDialog(
|
|||||||
taskView.startActivity(
|
taskView.startActivity(
|
||||||
PendingIntent.getActivity(context, 0, launchIntent,
|
PendingIntent.getActivity(context, 0, launchIntent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
|
||||||
null,
|
null /* fillInIntent */,
|
||||||
options
|
options,
|
||||||
|
getTaskViewBounds()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +161,23 @@ class DetailDialog(
|
|||||||
taskView.setListener(cvh.uiExecutor, stateCallback)
|
taskView.setListener(cvh.uiExecutor, stateCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getTaskViewBounds(): Rect {
|
||||||
|
val wm = context.getSystemService(WindowManager::class.java)
|
||||||
|
val windowMetrics = wm.getCurrentWindowMetrics()
|
||||||
|
val rect = windowMetrics.bounds
|
||||||
|
val metricInsets = windowMetrics.windowInsets
|
||||||
|
val insets = metricInsets.getInsetsIgnoringVisibility(Type.systemBars()
|
||||||
|
or Type.displayCutout())
|
||||||
|
val headerHeight = context.resources.getDimensionPixelSize(
|
||||||
|
R.dimen.controls_detail_dialog_header_height)
|
||||||
|
|
||||||
|
val finalRect = Rect(rect.left - insets.left /* left */,
|
||||||
|
rect.top + insets.top + headerHeight /* top */,
|
||||||
|
rect.right - insets.right /* right */,
|
||||||
|
rect.bottom - insets.bottom /* bottom */)
|
||||||
|
return finalRect
|
||||||
|
}
|
||||||
|
|
||||||
override fun dismiss() {
|
override fun dismiss() {
|
||||||
if (!isShowing()) return
|
if (!isShowing()) return
|
||||||
taskView.release()
|
taskView.release()
|
||||||
|
|||||||
@@ -160,8 +160,7 @@ class LaunchParamsController {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task.getRootTask().inFreeformWindowingMode()) {
|
if (task.getRootTask().inMultiWindowMode()) {
|
||||||
// Only set bounds if it's in freeform mode.
|
|
||||||
task.setBounds(mTmpParams.mBounds);
|
task.setBounds(mTmpParams.mBounds);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.server.wm;
|
|||||||
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
||||||
@@ -195,6 +196,11 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
|
|||||||
} else {
|
} else {
|
||||||
if (DEBUG) appendLog("empty-window-layout");
|
if (DEBUG) appendLog("empty-window-layout");
|
||||||
}
|
}
|
||||||
|
} else if (launchMode == WINDOWING_MODE_MULTI_WINDOW
|
||||||
|
&& options != null && options.getLaunchBounds() != null) {
|
||||||
|
outParams.mBounds.set(options.getLaunchBounds());
|
||||||
|
hasInitialBounds = true;
|
||||||
|
if (DEBUG) appendLog("multiwindow-activity-options-bounds=" + outParams.mBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP 2.2: Check if previous modifier or the controller (referred as "callers" below) has
|
// STEP 2.2: Check if previous modifier or the controller (referred as "callers" below) has
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.server.wm;
|
|||||||
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||||
import static android.view.Display.INVALID_DISPLAY;
|
import static android.view.Display.INVALID_DISPLAY;
|
||||||
@@ -371,6 +372,29 @@ public class LaunchParamsControllerTests extends WindowTestsBase {
|
|||||||
assertEquals(expected, task.getRequestedOverrideBounds());
|
assertEquals(expected, task.getRequestedOverrideBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that {@link LaunchParamsModifier} requests specifying bounds during
|
||||||
|
* layout are honored if window is in multiwindow mode.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLayoutTaskBoundsChangeMultiWindow() {
|
||||||
|
final Rect expected = new Rect(10, 20, 30, 40);
|
||||||
|
|
||||||
|
final LaunchParams params = new LaunchParams();
|
||||||
|
params.mWindowingMode = WINDOWING_MODE_MULTI_WINDOW;
|
||||||
|
params.mBounds.set(expected);
|
||||||
|
final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params);
|
||||||
|
final Task task = new TaskBuilder(mAtm.mTaskSupervisor).build();
|
||||||
|
|
||||||
|
mController.registerModifier(positioner);
|
||||||
|
|
||||||
|
assertNotEquals(expected, task.getBounds());
|
||||||
|
|
||||||
|
mController.layoutTask(task, null /* windowLayout */);
|
||||||
|
|
||||||
|
assertEquals(expected, task.getRequestedOverrideBounds());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that {@link LaunchParamsModifier} requests specifying bounds during
|
* Ensures that {@link LaunchParamsModifier} requests specifying bounds during
|
||||||
* layout are set to last non-fullscreen bounds.
|
* layout are set to last non-fullscreen bounds.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
|||||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
|
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
|
||||||
@@ -926,6 +927,25 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
|||||||
assertEquals(expected, mResult.mBounds);
|
assertEquals(expected, mResult.mBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKeepsBoundsForMultiWindowModeInOptions() {
|
||||||
|
final TestDisplayContent freeformDisplay = createNewDisplayContent(
|
||||||
|
WINDOWING_MODE_FULLSCREEN);
|
||||||
|
|
||||||
|
final ActivityOptions options = ActivityOptions.makeBasic();
|
||||||
|
options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
|
||||||
|
|
||||||
|
final Rect expected = new Rect(0, 0, 100, 100);
|
||||||
|
options.setLaunchBounds(expected);
|
||||||
|
|
||||||
|
mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
|
||||||
|
|
||||||
|
assertEquals(RESULT_CONTINUE,
|
||||||
|
new CalculateRequestBuilder().setOptions(options).calculate());
|
||||||
|
|
||||||
|
assertEquals(expected, mResult.mBounds);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRespectsLaunchBoundsWithFreeformSourceOnFullscreenDisplay() {
|
public void testRespectsLaunchBoundsWithFreeformSourceOnFullscreenDisplay() {
|
||||||
final TestDisplayContent fullscreenDisplay = createNewDisplayContent(
|
final TestDisplayContent fullscreenDisplay = createNewDisplayContent(
|
||||||
|
|||||||
Reference in New Issue
Block a user