Merge "Consolidate mTaskBounds logic to mConfiguration" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2022-11-24 12:39:07 +00:00
committed by Android (Google) Code Review
9 changed files with 74 additions and 101 deletions

View File

@@ -227,12 +227,13 @@ public class ActivityClient {
}
/**
* Returns the windowing mode of the task that hosts the activity, or {@code -1} if task is not
* found.
* Returns the {@link Configuration} of the task which hosts the Activity, or {@code null} if
* the task {@link Configuration} cannot be obtained.
*/
public int getTaskWindowingMode(IBinder activityToken) {
@Nullable
public Configuration getTaskConfiguration(IBinder activityToken) {
try {
return getActivityClientController().getTaskWindowingMode(activityToken);
return getActivityClientController().getTaskConfiguration(activityToken);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -78,7 +78,11 @@ interface IActivityClientController {
boolean willActivityBeVisible(in IBinder token);
int getDisplayId(in IBinder activityToken);
int getTaskForActivity(in IBinder token, in boolean onlyRoot);
int getTaskWindowingMode(in IBinder activityToken);
/**
* Returns the {@link Configuration} of the task which hosts the Activity, or {@code null} if
* the task {@link Configuration} cannot be obtained.
*/
Configuration getTaskConfiguration(in IBinder activityToken);
IBinder getActivityTokenBelow(IBinder token);
ComponentName getCallingActivity(in IBinder token);
String getCallingPackage(in IBinder token);

View File

@@ -41,7 +41,6 @@ import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAs
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenStacked;
import static androidx.window.extensions.embedding.SplitPresenter.RESULT_EXPAND_FAILED_NO_TF_INFO;
import static androidx.window.extensions.embedding.SplitPresenter.getActivityIntentMinDimensionsPair;
import static androidx.window.extensions.embedding.SplitPresenter.getNonEmbeddedActivityBounds;
import static androidx.window.extensions.embedding.SplitPresenter.shouldShowSplit;
import android.app.Activity;
@@ -464,7 +463,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// parentInfo#isVisibleRequested is true.
return;
}
onTaskContainerInfoChanged(taskContainer, parentInfo.getConfiguration());
if (isInPictureInPicture(parentInfo.getConfiguration())) {
// No need to update presentation in PIP until the Task exit PIP.
return;
@@ -614,12 +612,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
}
@GuardedBy("mLock")
private void onTaskContainerInfoChanged(@NonNull TaskContainer taskContainer,
@NonNull Configuration config) {
taskContainer.setTaskBounds(config.windowConfiguration.getBounds());
}
/** Returns whether the given {@link TaskContainer} may show in split. */
// Suppress GuardedBy warning because lint asks to mark this method as
// @GuardedBy(mPresenter.mController.mLock), which is mLock itself
@@ -1235,13 +1227,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
final TaskContainer taskContainer = mTaskContainers.get(taskId);
final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
pendingAppearedIntent, taskContainer, this);
if (!taskContainer.isTaskBoundsInitialized()) {
// Get the initial bounds before the TaskFragment has appeared.
final Rect taskBounds = getNonEmbeddedActivityBounds(activityInTask);
if (!taskContainer.setTaskBounds(taskBounds)) {
Log.w(TAG, "Can't find bounds from activity=" + activityInTask);
}
}
return container;
}

View File

@@ -932,11 +932,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
if (taskContainer != null) {
return taskContainer.getTaskProperties();
}
// Use a copy of configuration because activity's configuration may be updated later,
// or we may get unexpected TaskContainer's configuration if Activity's configuration is
// updated. An example is Activity is going to be in split.
return new TaskProperties(activity.getDisplayId(),
new Configuration(activity.getResources().getConfiguration()));
return TaskProperties.getTaskPropertiesFromActivity(activity);
}
@NonNull
@@ -950,16 +946,4 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
// TODO(b/190433398): Supply correct insets.
return new WindowMetrics(taskBounds, WindowInsets.CONSUMED);
}
/** Obtains the bounds from a non-embedded Activity. */
@NonNull
static Rect getNonEmbeddedActivityBounds(@NonNull Activity activity) {
final WindowConfiguration windowConfiguration =
activity.getResources().getConfiguration().windowConfiguration;
if (!activity.isInMultiWindowMode()) {
// In fullscreen mode the max bounds should correspond to the task bounds.
return windowConfiguration.getMaxBounds();
}
return windowConfiguration.getBounds();
}
}

View File

@@ -20,14 +20,17 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.inMultiWindowMode;
import android.app.Activity;
import android.app.ActivityClient;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.ArraySet;
import android.util.Log;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentParentInfo;
import android.window.WindowContainerTransaction;
@@ -41,14 +44,11 @@ import java.util.Set;
/** Represents TaskFragments and split pairs below a Task. */
class TaskContainer {
private static final String TAG = TaskContainer.class.getSimpleName();
/** The unique task id. */
private final int mTaskId;
// TODO(b/240219484): consolidate to mConfiguration
/** Available window bounds of this Task. */
private final Rect mTaskBounds = new Rect();
/** Active TaskFragments in this Task. */
@NonNull
final List<TaskFragmentContainer> mContainers = new ArrayList<>();
@@ -86,10 +86,10 @@ class TaskContainer {
throw new IllegalArgumentException("Invalid Task id");
}
mTaskId = taskId;
// Make a copy in case the activity's config is updated, and updates the TaskContainer's
// config unexpectedly.
mConfiguration = new Configuration(activityInTask.getResources().getConfiguration());
mDisplayId = activityInTask.getDisplayId();
final TaskProperties taskProperties = TaskProperties
.getTaskPropertiesFromActivity(activityInTask);
mConfiguration = taskProperties.getConfiguration();
mDisplayId = taskProperties.getDisplayId();
// Note that it is always called when there's a new Activity is started, which implies
// the host task is visible.
mIsVisible = true;
@@ -107,25 +107,6 @@ class TaskContainer {
return mIsVisible;
}
@NonNull
Rect getTaskBounds() {
return mTaskBounds;
}
/** Returns {@code true} if the bounds is changed. */
boolean setTaskBounds(@NonNull Rect taskBounds) {
if (!taskBounds.isEmpty() && !mTaskBounds.equals(taskBounds)) {
mTaskBounds.set(taskBounds);
return true;
}
return false;
}
/** Whether the Task bounds has been initialized. */
boolean isTaskBoundsInitialized() {
return !mTaskBounds.isEmpty();
}
@NonNull
Configuration getConfiguration() {
// Make a copy in case the config is updated unexpectedly.
@@ -261,5 +242,45 @@ class TaskContainer {
Configuration getConfiguration() {
return mConfiguration;
}
/**
* Obtains the {@link TaskProperties} for the task that the provided {@link Activity} is
* associated with.
* <p>
* Note that for most case, caller should use
* {@link SplitPresenter#getTaskProperties(Activity)} instead. This method is used before
* the {@code activity} goes into split.
* </p><p>
* If the {@link Activity} is in fullscreen, override
* {@link WindowConfiguration#getBounds()} with {@link WindowConfiguration#getMaxBounds()}
* in case the {@link Activity} is letterboxed. Otherwise, get the Task
* {@link Configuration} from the server side or use {@link Activity}'s
* {@link Configuration} as a fallback if the Task {@link Configuration} cannot be obtained.
*/
@NonNull
static TaskProperties getTaskPropertiesFromActivity(@NonNull Activity activity) {
final int displayId = activity.getDisplayId();
// Use a copy of configuration because activity's configuration may be updated later,
// or we may get unexpected TaskContainer's configuration if Activity's configuration is
// updated. An example is Activity is going to be in split.
final Configuration activityConfig = new Configuration(
activity.getResources().getConfiguration());
final WindowConfiguration windowConfiguration = activityConfig.windowConfiguration;
final int windowingMode = windowConfiguration.getWindowingMode();
if (!inMultiWindowMode(windowingMode)) {
// Use the max bounds in fullscreen in case the Activity is letterboxed.
windowConfiguration.setBounds(windowConfiguration.getMaxBounds());
return new TaskProperties(displayId, activityConfig);
}
final Configuration taskConfig = ActivityClient.getInstance()
.getTaskConfiguration(activity.getActivityToken());
if (taskConfig == null) {
Log.w(TAG, "Could not obtain task configuration for activity:" + activity);
// Still report activity config if task config cannot be obtained from the server
// side.
return new TaskProperties(displayId, activityConfig);
}
return new TaskProperties(displayId, taskConfig);
}
}
}

View File

@@ -35,7 +35,6 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.util.ArrayMap;
import android.window.WindowContext;
import android.window.WindowProvider;
import androidx.annotation.NonNull;
@@ -310,20 +309,21 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
}
final int windowingMode;
if (context instanceof Activity) {
windowingMode = ActivityClient.getInstance().getTaskWindowingMode(
final Configuration taskConfig = ActivityClient.getInstance().getTaskConfiguration(
context.getActivityToken());
if (taskConfig == null) {
// If we cannot determine the task configuration for any reason, it is likely that
// we won't be able to determine its position correctly as well. DisplayFeatures'
// bounds in this case can't be computed correctly, so we should skip.
return false;
}
windowingMode = taskConfig.windowConfiguration.getWindowingMode();
} else {
// TODO(b/242674941): use task windowing mode for window context that associates with
// activity.
windowingMode = context.getResources().getConfiguration().windowConfiguration
.getWindowingMode();
}
if (windowingMode == -1) {
// If we cannot determine the task windowing mode for any reason, it is likely that we
// won't be able to determine its position correctly as well. DisplayFeatures' bounds
// in this case can't be computed correctly, so we should skip.
return false;
}
// It is recommended not to report any display features in multi-window mode, since it
// won't be possible to synchronize the display feature positions with window movement.
return !WindowConfiguration.inMultiWindowMode(windowingMode);

View File

@@ -261,7 +261,7 @@ public class SplitControllerTest {
assertNotNull(tf);
assertNotNull(taskContainer);
assertEquals(TASK_BOUNDS, taskContainer.getTaskBounds());
assertEquals(TASK_BOUNDS, taskContainer.getConfiguration().windowConfiguration.getBounds());
}
@Test

View File

@@ -23,7 +23,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTestTaskContainer;
import static org.junit.Assert.assertEquals;
@@ -67,28 +66,6 @@ public class TaskContainerTest {
MockitoAnnotations.initMocks(this);
}
@Test
public void testIsTaskBoundsInitialized() {
final TaskContainer taskContainer = createTestTaskContainer();
assertFalse(taskContainer.isTaskBoundsInitialized());
taskContainer.setTaskBounds(TASK_BOUNDS);
assertTrue(taskContainer.isTaskBoundsInitialized());
}
@Test
public void testSetTaskBounds() {
final TaskContainer taskContainer = createTestTaskContainer();
assertFalse(taskContainer.setTaskBounds(new Rect()));
assertTrue(taskContainer.setTaskBounds(TASK_BOUNDS));
assertFalse(taskContainer.setTaskBounds(TASK_BOUNDS));
}
@Test
public void testGetWindowingModeForSplitTaskFragment() {
final TaskContainer taskContainer = createTestTaskContainer();

View File

@@ -580,17 +580,18 @@ class ActivityClientController extends IActivityClientController.Stub {
}
/**
* Returns the windowing mode of the task that hosts the activity, or {@code -1} if task is not
* found.
* Returns the {@link Configuration} of the task which hosts the Activity, or {@code null} if
* the task {@link Configuration} cannot be obtained.
*/
@Override
public int getTaskWindowingMode(IBinder activityToken) {
@Nullable
public Configuration getTaskConfiguration(IBinder activityToken) {
synchronized (mGlobalLock) {
final ActivityRecord ar = ActivityRecord.isInAnyTask(activityToken);
if (ar == null) {
return -1;
return null;
}
return ar.getTask().getWindowingMode();
return ar.getTask().getConfiguration();
}
}