Notify TaskFragmentOrganizer onConfigurationChanged
Bug: 190433129 Bug: 190433500 Test: N/A Change-Id: I383a434d536ac08f7cf82dfd87cd24bfc53a6d58
This commit is contained in:
@@ -331,11 +331,10 @@ public class TaskInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if parameters that are important for task organizers have changed
|
||||
* and {@link com.android.server.wm.TaskOrginizerController} needs to notify listeners
|
||||
* about that.
|
||||
* @hide
|
||||
*/
|
||||
* Returns {@code true} if the parameters that are important for task organizers are equal
|
||||
* between this {@link TaskInfo} and {@param that}.
|
||||
* @hide
|
||||
*/
|
||||
public boolean equalsForTaskOrganizer(@Nullable TaskInfo that) {
|
||||
if (that == null) {
|
||||
return false;
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
package android.window;
|
||||
|
||||
import static android.app.WindowConfiguration.WindowingMode;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.IBinder;
|
||||
@@ -94,6 +97,28 @@ public final class TaskFragmentInfo implements Parcelable {
|
||||
return mIsVisible;
|
||||
}
|
||||
|
||||
@WindowingMode
|
||||
public int getWindowingMode() {
|
||||
return mConfiguration.windowConfiguration.getWindowingMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the parameters that are important for task fragment organizers are
|
||||
* equal between this {@link TaskFragmentInfo} and {@param that}.
|
||||
*/
|
||||
public boolean equalsForTaskFragmentOrganizer(@Nullable TaskFragmentInfo that) {
|
||||
if (that == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mFragmentToken.equals(that.mFragmentToken)
|
||||
&& mInitialComponentName.equals(that.mInitialComponentName)
|
||||
&& mToken.equals(that.mToken)
|
||||
&& mIsEmpty == that.mIsEmpty
|
||||
&& mIsVisible == that.mIsVisible
|
||||
&& getWindowingMode() == that.getWindowingMode();
|
||||
}
|
||||
|
||||
private TaskFragmentInfo(Parcel in) {
|
||||
mFragmentToken = in.readStrongBinder();
|
||||
mInitialComponentName = in.readTypedObject(ComponentName.CREATOR);
|
||||
|
||||
@@ -142,6 +142,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
final ActivityTaskManagerService mAtmService;
|
||||
final ActivityTaskSupervisor mTaskSupervisor;
|
||||
final RootWindowContainer mRootWindowContainer;
|
||||
private final TaskFragmentOrganizerController mTaskFragmentOrganizerController;
|
||||
|
||||
// TODO(b/189384393): this is not set in TaskFragment so far. It should be passed from the
|
||||
// parent task when adding to the hierarchy
|
||||
@@ -272,6 +273,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
mTaskSupervisor = atmService.mTaskSupervisor;
|
||||
mRootWindowContainer = mAtmService.mRootWindowContainer;
|
||||
mCreatedByOrganizer = createdByOrganizer;
|
||||
mTaskFragmentOrganizerController =
|
||||
mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController;
|
||||
}
|
||||
|
||||
void setAdjacentTaskFragment(TaskFragment taskFragment) {
|
||||
@@ -1937,6 +1940,34 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
return getTopChild().getActivityType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newParentConfig) {
|
||||
super.onConfigurationChanged(newParentConfig);
|
||||
|
||||
if (mTaskFragmentOrganizer != null) {
|
||||
// Parent config may have changed. The controller will check if there is any important
|
||||
// config change for the organizer.
|
||||
mTaskFragmentOrganizerController
|
||||
.onTaskFragmentParentInfoChanged(mTaskFragmentOrganizer, this);
|
||||
mTaskFragmentOrganizerController
|
||||
.onTaskFragmentInfoChanged(mTaskFragmentOrganizer, this);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/190433129) call when TaskFragment is created from WCT#createTaskFragment
|
||||
private void sendTaskFragmentAppeared() {
|
||||
if (mTaskFragmentOrganizer != null) {
|
||||
mTaskFragmentOrganizerController.onTaskFragmentAppeared(mTaskFragmentOrganizer, this);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/190433129) call when TaskFragment is removed from WCT#deleteTaskFragment
|
||||
private void sendTaskFragmentVanished() {
|
||||
if (mTaskFragmentOrganizer != null) {
|
||||
mTaskFragmentOrganizerController.onTaskFragmentVanished(mTaskFragmentOrganizer, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link TaskFragmentInfo} with information from this TaskFragment. Should not be
|
||||
* called from {@link Task}.
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
|
||||
import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -27,11 +29,13 @@ import android.view.SurfaceControl;
|
||||
import android.window.ITaskFragmentOrganizer;
|
||||
import android.window.ITaskFragmentOrganizerController;
|
||||
import android.window.TaskFragmentAppearedInfo;
|
||||
import android.window.TaskFragmentInfo;
|
||||
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* Stores and manages the client {@link android.window.TaskFragmentOrganizer}.
|
||||
@@ -43,6 +47,10 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
private final WindowManagerGlobalLock mGlobalLock;
|
||||
private final Set<ITaskFragmentOrganizer> mOrganizers = new ArraySet<>();
|
||||
private final Map<ITaskFragmentOrganizer, DeathRecipient> mDeathRecipients = new ArrayMap<>();
|
||||
private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
|
||||
new WeakHashMap<>();
|
||||
private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
|
||||
new WeakHashMap<>();
|
||||
|
||||
private class DeathRecipient implements IBinder.DeathRecipient {
|
||||
final ITaskFragmentOrganizer mOrganizer;
|
||||
@@ -118,43 +126,75 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
}
|
||||
|
||||
void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
||||
validateOrganizer(organizer);
|
||||
|
||||
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
|
||||
final TaskFragmentInfo info = tf.getTaskFragmentInfo();
|
||||
final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(),
|
||||
"TaskFragmentOrganizerController.onTaskFragmentInfoAppeared");
|
||||
try {
|
||||
final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(),
|
||||
"TaskFragmentOrganizerController.onTaskFragmentInfoAppeared");
|
||||
organizer.onTaskFragmentAppeared(
|
||||
new TaskFragmentAppearedInfo(tf.getTaskFragmentInfo(), outSurfaceControl));
|
||||
new TaskFragmentAppearedInfo(info, outSurfaceControl));
|
||||
mLastSentTaskFragmentInfos.put(tf, info);
|
||||
} catch (RemoteException e) {
|
||||
// Oh well...
|
||||
}
|
||||
}
|
||||
|
||||
void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
||||
validateOrganizer(organizer);
|
||||
|
||||
// Check if the info is different from the last reported info.
|
||||
final TaskFragmentInfo info = tf.getTaskFragmentInfo();
|
||||
final TaskFragmentInfo lastInfo = mLastSentTaskFragmentInfos.get(tf);
|
||||
if (info.equalsForTaskFragmentOrganizer(lastInfo) && configurationsAreEqualForOrganizer(
|
||||
info.getConfiguration(), lastInfo.getConfiguration())) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s", tf.getName());
|
||||
try {
|
||||
organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
|
||||
mLastSentTaskFragmentInfos.put(tf, info);
|
||||
} catch (RemoteException e) {
|
||||
// Oh well...
|
||||
}
|
||||
}
|
||||
|
||||
void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
||||
validateOrganizer(organizer);
|
||||
|
||||
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
|
||||
try {
|
||||
organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
|
||||
} catch (RemoteException e) {
|
||||
// Oh well...
|
||||
}
|
||||
mLastSentTaskFragmentInfos.remove(tf);
|
||||
mLastSentTaskFragmentParentConfigs.remove(tf);
|
||||
}
|
||||
|
||||
void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
||||
validateOrganizer(organizer);
|
||||
|
||||
// Check if the parent info is different from the last reported parent info.
|
||||
if (tf.getParent() == null || tf.getParent().asTask() == null) {
|
||||
mLastSentTaskFragmentParentConfigs.remove(tf);
|
||||
return;
|
||||
}
|
||||
final Task parent = tf.getParent().asTask();
|
||||
final Configuration parentConfig = parent.getConfiguration();
|
||||
final Configuration lastParentConfig = mLastSentTaskFragmentParentConfigs.get(tf);
|
||||
if (configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
|
||||
"TaskFragment parent info changed name=%s parentTaskId=%d",
|
||||
tf.getName(), parent.mTaskId);
|
||||
try {
|
||||
organizer.onTaskFragmentParentInfoChanged(
|
||||
tf.getFragmentToken(), parent.getConfiguration());
|
||||
organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig);
|
||||
mLastSentTaskFragmentParentConfigs.put(tf, parentConfig);
|
||||
} catch (RemoteException e) {
|
||||
// Oh well...
|
||||
}
|
||||
@@ -167,4 +207,17 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
||||
}
|
||||
// TODO(b/190432728) move child activities of organized TaskFragment to leaf Task
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the organizer has been correctly registered to prevent any Sidecar
|
||||
* implementation from organizing {@link TaskFragment} without registering first. In such case,
|
||||
* we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the
|
||||
* {@link TaskFragment} after the organizer process died.
|
||||
*/
|
||||
private void validateOrganizer(ITaskFragmentOrganizer organizer) {
|
||||
if (!mOrganizers.contains(organizer)) {
|
||||
throw new IllegalArgumentException(
|
||||
"TaskFragmentOrganizer has not been registered. Organizer=" + organizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,15 +23,13 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANI
|
||||
import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
|
||||
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
|
||||
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL;
|
||||
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS;
|
||||
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS;
|
||||
import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
@@ -69,13 +67,6 @@ import java.util.function.Consumer;
|
||||
class TaskOrganizerController extends ITaskOrganizerController.Stub {
|
||||
private static final String TAG = "TaskOrganizerController";
|
||||
|
||||
/**
|
||||
* Masks specifying which configurations are important to report back to an organizer when
|
||||
* changed.
|
||||
*/
|
||||
private static final int REPORT_CONFIGS = CONTROLLABLE_CONFIGS;
|
||||
private static final int REPORT_WINDOW_CONFIGS = CONTROLLABLE_WINDOW_CONFIGS;
|
||||
|
||||
// The set of modes that are currently supports
|
||||
// TODO: Remove once the task organizer can support all modes
|
||||
@VisibleForTesting
|
||||
@@ -790,18 +781,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
|
||||
mTmpTaskInfo.configuration.unset();
|
||||
task.fillTaskInfo(mTmpTaskInfo);
|
||||
|
||||
boolean changed = !mTmpTaskInfo.equalsForTaskOrganizer(lastInfo);
|
||||
if (!changed) {
|
||||
int cfgChanges = mTmpTaskInfo.configuration.diff(lastInfo.configuration);
|
||||
final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0
|
||||
? (int) mTmpTaskInfo.configuration.windowConfiguration.diff(
|
||||
lastInfo.configuration.windowConfiguration,
|
||||
true /* compareUndefined */) : 0;
|
||||
if ((winCfgChanges & REPORT_WINDOW_CONFIGS) == 0) {
|
||||
cfgChanges &= ~ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
|
||||
}
|
||||
changed = (cfgChanges & REPORT_CONFIGS) != 0;
|
||||
}
|
||||
boolean changed = !mTmpTaskInfo.equalsForTaskOrganizer(lastInfo)
|
||||
|| !configurationsAreEqualForOrganizer(
|
||||
mTmpTaskInfo.configuration, lastInfo.configuration);
|
||||
if (!(changed || force)) {
|
||||
// mTmpTaskInfo will be reused next time.
|
||||
return;
|
||||
|
||||
@@ -847,6 +847,22 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/** Whether the configuration changes are important to report back to an organizer. */
|
||||
static boolean configurationsAreEqualForOrganizer(
|
||||
Configuration newConfig, @Nullable Configuration oldConfig) {
|
||||
if (oldConfig == null) {
|
||||
return false;
|
||||
}
|
||||
int cfgChanges = newConfig.diff(oldConfig);
|
||||
final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0
|
||||
? (int) newConfig.windowConfiguration.diff(oldConfig.windowConfiguration,
|
||||
true /* compareUndefined */) : 0;
|
||||
if ((winCfgChanges & CONTROLLABLE_WINDOW_CONFIGS) == 0) {
|
||||
cfgChanges &= ~ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
|
||||
}
|
||||
return (cfgChanges & CONTROLLABLE_CONFIGS) == 0;
|
||||
}
|
||||
|
||||
private void enforceTaskPermission(String func) {
|
||||
mService.enforceTaskPermission(func);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user