Loading core/java/android/window/TaskFragmentCreationParams.java +41 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.ScreenOrientation; import android.graphics.Rect; import android.os.IBinder; Loading Loading @@ -112,12 +113,21 @@ public final class TaskFragmentCreationParams implements Parcelable { */ private final @ScreenOrientation int mOverrideOrientation; /** * {@link android.content.pm.ActivityInfo.Config} mask that specifies which * configuration changes should trigger TaskFragment info change callbacks. * * @see android.content.pm.ActivityInfo.Config */ private final @ActivityInfo.Config int mConfigurationChangeMask; private TaskFragmentCreationParams( @NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken, @NonNull Rect initialRelativeBounds, @WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken, @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty, @ScreenOrientation int overrideOrientation) { @ScreenOrientation int overrideOrientation, @ActivityInfo.Config int configurationChangeMask) { if (pairedPrimaryFragmentToken != null && pairedActivityToken != null) { throw new IllegalArgumentException("pairedPrimaryFragmentToken and" + " pairedActivityToken should not be set at the same time."); Loading @@ -131,6 +141,7 @@ public final class TaskFragmentCreationParams implements Parcelable { mPairedActivityToken = pairedActivityToken; mAllowTransitionWhenEmpty = allowTransitionWhenEmpty; mOverrideOrientation = overrideOrientation; mConfigurationChangeMask = configurationChangeMask; } @NonNull Loading Loading @@ -186,6 +197,11 @@ public final class TaskFragmentCreationParams implements Parcelable { return mOverrideOrientation; } /** @hide */ public @ActivityInfo.Config int getConfigurationChangeMask() { return mConfigurationChangeMask; } private TaskFragmentCreationParams(Parcel in) { mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in); mFragmentToken = in.readStrongBinder(); Loading @@ -196,6 +212,7 @@ public final class TaskFragmentCreationParams implements Parcelable { mPairedActivityToken = in.readStrongBinder(); mAllowTransitionWhenEmpty = in.readBoolean(); mOverrideOrientation = in.readInt(); mConfigurationChangeMask = in.readInt(); } /** @hide */ Loading @@ -210,6 +227,7 @@ public final class TaskFragmentCreationParams implements Parcelable { dest.writeStrongBinder(mPairedActivityToken); dest.writeBoolean(mAllowTransitionWhenEmpty); dest.writeInt(mOverrideOrientation); dest.writeInt(mConfigurationChangeMask); } @NonNull Loading Loading @@ -238,6 +256,7 @@ public final class TaskFragmentCreationParams implements Parcelable { + " pairedActivityToken=" + mPairedActivityToken + " allowTransitionWhenEmpty=" + mAllowTransitionWhenEmpty + " overrideOrientation=" + mOverrideOrientation + " configurationChangeMask=" + mConfigurationChangeMask + "}"; } Loading Loading @@ -275,6 +294,8 @@ public final class TaskFragmentCreationParams implements Parcelable { private @ScreenOrientation int mOverrideOrientation = SCREEN_ORIENTATION_UNSPECIFIED; private @ActivityInfo.Config int mConfigurationChangeMask = 0; public Builder(@NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) { mOrganizer = organizer; Loading Loading @@ -369,12 +390,30 @@ public final class TaskFragmentCreationParams implements Parcelable { return this; } /** * Sets {@link android.content.pm.ActivityInfo.Config} mask that specifies which * configuration changes should trigger TaskFragment info change callbacks. * * Only system organizers are allowed to configure this value. This value is ignored for * non-system organizers. * * @see android.content.pm.ActivityInfo.Config * @hide */ @NonNull public Builder setConfigurationChangeMask( @ActivityInfo.Config int configurationChangeMask) { mConfigurationChangeMask = configurationChangeMask; return this; } /** Constructs the options to create TaskFragment with. */ @NonNull public TaskFragmentCreationParams build() { return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken, mInitialRelativeBounds, mWindowingMode, mPairedPrimaryFragmentToken, mPairedActivityToken, mAllowTransitionWhenEmpty, mOverrideOrientation); mPairedActivityToken, mAllowTransitionWhenEmpty, mOverrideOrientation, mConfigurationChangeMask); } } } services/core/java/com/android/server/wm/TaskFragment.java +17 −0 Original line number Diff line number Diff line Loading @@ -394,6 +394,12 @@ class TaskFragment extends WindowContainer<WindowContainer> { */ private boolean mAllowTransitionWhenEmpty; /** * Specifies which configuration changes should trigger TaskFragment info changed callbacks. * Only system TaskFragment organizers are allowed to set this value. */ private @ActivityInfo.Config int mConfigurationChangeMaskForOrganizer; /** When set, will force the task to report as invisible. */ static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1; static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; Loading Loading @@ -656,6 +662,17 @@ class TaskFragment extends WindowContainer<WindowContainer> { mAllowTransitionWhenEmpty = allowTransitionWhenEmpty; } void setConfigurationChangeMaskForOrganizer(@ActivityInfo.Config int mask) { // Only system organizers are allowed to set configuration change mask. if (mTaskFragmentOrganizerController.isSystemOrganizer(mTaskFragmentOrganizer.asBinder())) { mConfigurationChangeMaskForOrganizer = mask; } } @ActivityInfo.Config int getConfigurationChangeMaskForOrganizer() { return mConfigurationChangeMaskForOrganizer; } /** @see #mIsolatedNav */ boolean isIsolatedNav() { return isEmbedded() && mIsolatedNav; Loading services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +4 −2 Original line number Diff line number Diff line Loading @@ -349,8 +349,10 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr // 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())) { final int configurationChangeMask = tf.getConfigurationChangeMaskForOrganizer(); if (info.equalsForTaskFragmentOrganizer(lastInfo) && configurationsAreEqualForOrganizer(info.getConfiguration(), lastInfo.getConfiguration(), configurationChangeMask)) { return null; } Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +20 −0 Original line number Diff line number Diff line Loading @@ -2455,10 +2455,28 @@ 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) { return configurationsAreEqualForOrganizer(newConfig, oldConfig, 0 /* additionalMask */); } /** * Whether the configuration changes are important to report back to an organizer. * * @param newConfig the new configuration * @param oldConfig the old configuration * @param additionalMask specifies additional configuration changes that the organizer is * interested in. If the configuration change matches any bit in the mask, * {@code false} is returned. */ static boolean configurationsAreEqualForOrganizer( Configuration newConfig, @Nullable Configuration oldConfig, @ActivityInfo.Config int additionalMask) { if (oldConfig == null) { return false; } int cfgChanges = newConfig.diff(oldConfig); if ((cfgChanges & additionalMask) != 0) { return false; } final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0 ? (int) newConfig.windowConfiguration.diff(oldConfig.windowConfiguration, true /* compareUndefined */) : 0; Loading Loading @@ -2665,6 +2683,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub ownerActivity.getUid(), ownerActivity.info.processName); if (mTaskFragmentOrganizerController.isSystemOrganizer(organizerToken.asBinder())) { taskFragment.setOverrideOrientation(creationParams.getOverrideOrientation()); taskFragment.setConfigurationChangeMaskForOrganizer( creationParams.getConfigurationChangeMask()); } final int position; if (creationParams.getPairedPrimaryFragmentToken() != null) { Loading services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +27 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ 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_UNDEFINED; import static android.content.pm.ActivityInfo.CONFIG_UI_MODE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; Loading @@ -33,6 +34,8 @@ import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED; import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED; import static android.content.res.Configuration.UI_MODE_NIGHT_NO; import static android.content.res.Configuration.UI_MODE_NIGHT_YES; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; Loading Loading @@ -1983,6 +1986,30 @@ public class WindowOrganizerTests extends WindowTestsBase { testSetAlwaysOnTop(displayArea); } @Test public void testConfigurationsAreEqualForOrganizer() { Configuration config1 = new Configuration(); config1.smallestScreenWidthDp = 300; config1.uiMode = UI_MODE_NIGHT_YES; Configuration config2 = new Configuration(config1); config2.uiMode = UI_MODE_NIGHT_NO; Configuration config3 = new Configuration(config1); config3.smallestScreenWidthDp = 500; // Should be equal for non-controllable configuration changes. assertTrue(WindowOrganizerController.configurationsAreEqualForOrganizer(config1, config2)); // Should be unequal for non-controllable configuration changes if the organizer is // interested in that change. assertFalse(WindowOrganizerController.configurationsAreEqualForOrganizer( config1, config2, CONFIG_UI_MODE)); // Should be unequal for controllable configuration changes. assertFalse(WindowOrganizerController.configurationsAreEqualForOrganizer(config1, config3)); } private void testSetAlwaysOnTop(WindowContainer wc) { final WindowContainerTransaction t = new WindowContainerTransaction(); t.setAlwaysOnTop(wc.mRemoteToken.toWindowContainerToken(), true); Loading Loading
core/java/android/window/TaskFragmentCreationParams.java +41 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.ScreenOrientation; import android.graphics.Rect; import android.os.IBinder; Loading Loading @@ -112,12 +113,21 @@ public final class TaskFragmentCreationParams implements Parcelable { */ private final @ScreenOrientation int mOverrideOrientation; /** * {@link android.content.pm.ActivityInfo.Config} mask that specifies which * configuration changes should trigger TaskFragment info change callbacks. * * @see android.content.pm.ActivityInfo.Config */ private final @ActivityInfo.Config int mConfigurationChangeMask; private TaskFragmentCreationParams( @NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken, @NonNull Rect initialRelativeBounds, @WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken, @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty, @ScreenOrientation int overrideOrientation) { @ScreenOrientation int overrideOrientation, @ActivityInfo.Config int configurationChangeMask) { if (pairedPrimaryFragmentToken != null && pairedActivityToken != null) { throw new IllegalArgumentException("pairedPrimaryFragmentToken and" + " pairedActivityToken should not be set at the same time."); Loading @@ -131,6 +141,7 @@ public final class TaskFragmentCreationParams implements Parcelable { mPairedActivityToken = pairedActivityToken; mAllowTransitionWhenEmpty = allowTransitionWhenEmpty; mOverrideOrientation = overrideOrientation; mConfigurationChangeMask = configurationChangeMask; } @NonNull Loading Loading @@ -186,6 +197,11 @@ public final class TaskFragmentCreationParams implements Parcelable { return mOverrideOrientation; } /** @hide */ public @ActivityInfo.Config int getConfigurationChangeMask() { return mConfigurationChangeMask; } private TaskFragmentCreationParams(Parcel in) { mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in); mFragmentToken = in.readStrongBinder(); Loading @@ -196,6 +212,7 @@ public final class TaskFragmentCreationParams implements Parcelable { mPairedActivityToken = in.readStrongBinder(); mAllowTransitionWhenEmpty = in.readBoolean(); mOverrideOrientation = in.readInt(); mConfigurationChangeMask = in.readInt(); } /** @hide */ Loading @@ -210,6 +227,7 @@ public final class TaskFragmentCreationParams implements Parcelable { dest.writeStrongBinder(mPairedActivityToken); dest.writeBoolean(mAllowTransitionWhenEmpty); dest.writeInt(mOverrideOrientation); dest.writeInt(mConfigurationChangeMask); } @NonNull Loading Loading @@ -238,6 +256,7 @@ public final class TaskFragmentCreationParams implements Parcelable { + " pairedActivityToken=" + mPairedActivityToken + " allowTransitionWhenEmpty=" + mAllowTransitionWhenEmpty + " overrideOrientation=" + mOverrideOrientation + " configurationChangeMask=" + mConfigurationChangeMask + "}"; } Loading Loading @@ -275,6 +294,8 @@ public final class TaskFragmentCreationParams implements Parcelable { private @ScreenOrientation int mOverrideOrientation = SCREEN_ORIENTATION_UNSPECIFIED; private @ActivityInfo.Config int mConfigurationChangeMask = 0; public Builder(@NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) { mOrganizer = organizer; Loading Loading @@ -369,12 +390,30 @@ public final class TaskFragmentCreationParams implements Parcelable { return this; } /** * Sets {@link android.content.pm.ActivityInfo.Config} mask that specifies which * configuration changes should trigger TaskFragment info change callbacks. * * Only system organizers are allowed to configure this value. This value is ignored for * non-system organizers. * * @see android.content.pm.ActivityInfo.Config * @hide */ @NonNull public Builder setConfigurationChangeMask( @ActivityInfo.Config int configurationChangeMask) { mConfigurationChangeMask = configurationChangeMask; return this; } /** Constructs the options to create TaskFragment with. */ @NonNull public TaskFragmentCreationParams build() { return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken, mInitialRelativeBounds, mWindowingMode, mPairedPrimaryFragmentToken, mPairedActivityToken, mAllowTransitionWhenEmpty, mOverrideOrientation); mPairedActivityToken, mAllowTransitionWhenEmpty, mOverrideOrientation, mConfigurationChangeMask); } } }
services/core/java/com/android/server/wm/TaskFragment.java +17 −0 Original line number Diff line number Diff line Loading @@ -394,6 +394,12 @@ class TaskFragment extends WindowContainer<WindowContainer> { */ private boolean mAllowTransitionWhenEmpty; /** * Specifies which configuration changes should trigger TaskFragment info changed callbacks. * Only system TaskFragment organizers are allowed to set this value. */ private @ActivityInfo.Config int mConfigurationChangeMaskForOrganizer; /** When set, will force the task to report as invisible. */ static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1; static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; Loading Loading @@ -656,6 +662,17 @@ class TaskFragment extends WindowContainer<WindowContainer> { mAllowTransitionWhenEmpty = allowTransitionWhenEmpty; } void setConfigurationChangeMaskForOrganizer(@ActivityInfo.Config int mask) { // Only system organizers are allowed to set configuration change mask. if (mTaskFragmentOrganizerController.isSystemOrganizer(mTaskFragmentOrganizer.asBinder())) { mConfigurationChangeMaskForOrganizer = mask; } } @ActivityInfo.Config int getConfigurationChangeMaskForOrganizer() { return mConfigurationChangeMaskForOrganizer; } /** @see #mIsolatedNav */ boolean isIsolatedNav() { return isEmbedded() && mIsolatedNav; Loading
services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +4 −2 Original line number Diff line number Diff line Loading @@ -349,8 +349,10 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr // 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())) { final int configurationChangeMask = tf.getConfigurationChangeMaskForOrganizer(); if (info.equalsForTaskFragmentOrganizer(lastInfo) && configurationsAreEqualForOrganizer(info.getConfiguration(), lastInfo.getConfiguration(), configurationChangeMask)) { return null; } Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +20 −0 Original line number Diff line number Diff line Loading @@ -2455,10 +2455,28 @@ 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) { return configurationsAreEqualForOrganizer(newConfig, oldConfig, 0 /* additionalMask */); } /** * Whether the configuration changes are important to report back to an organizer. * * @param newConfig the new configuration * @param oldConfig the old configuration * @param additionalMask specifies additional configuration changes that the organizer is * interested in. If the configuration change matches any bit in the mask, * {@code false} is returned. */ static boolean configurationsAreEqualForOrganizer( Configuration newConfig, @Nullable Configuration oldConfig, @ActivityInfo.Config int additionalMask) { if (oldConfig == null) { return false; } int cfgChanges = newConfig.diff(oldConfig); if ((cfgChanges & additionalMask) != 0) { return false; } final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0 ? (int) newConfig.windowConfiguration.diff(oldConfig.windowConfiguration, true /* compareUndefined */) : 0; Loading Loading @@ -2665,6 +2683,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub ownerActivity.getUid(), ownerActivity.info.processName); if (mTaskFragmentOrganizerController.isSystemOrganizer(organizerToken.asBinder())) { taskFragment.setOverrideOrientation(creationParams.getOverrideOrientation()); taskFragment.setConfigurationChangeMaskForOrganizer( creationParams.getConfigurationChangeMask()); } final int position; if (creationParams.getPairedPrimaryFragmentToken() != null) { Loading
services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +27 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ 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_UNDEFINED; import static android.content.pm.ActivityInfo.CONFIG_UI_MODE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; Loading @@ -33,6 +34,8 @@ import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED; import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED; import static android.content.res.Configuration.UI_MODE_NIGHT_NO; import static android.content.res.Configuration.UI_MODE_NIGHT_YES; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; Loading Loading @@ -1983,6 +1986,30 @@ public class WindowOrganizerTests extends WindowTestsBase { testSetAlwaysOnTop(displayArea); } @Test public void testConfigurationsAreEqualForOrganizer() { Configuration config1 = new Configuration(); config1.smallestScreenWidthDp = 300; config1.uiMode = UI_MODE_NIGHT_YES; Configuration config2 = new Configuration(config1); config2.uiMode = UI_MODE_NIGHT_NO; Configuration config3 = new Configuration(config1); config3.smallestScreenWidthDp = 500; // Should be equal for non-controllable configuration changes. assertTrue(WindowOrganizerController.configurationsAreEqualForOrganizer(config1, config2)); // Should be unequal for non-controllable configuration changes if the organizer is // interested in that change. assertFalse(WindowOrganizerController.configurationsAreEqualForOrganizer( config1, config2, CONFIG_UI_MODE)); // Should be unequal for controllable configuration changes. assertFalse(WindowOrganizerController.configurationsAreEqualForOrganizer(config1, config3)); } private void testSetAlwaysOnTop(WindowContainer wc) { final WindowContainerTransaction t = new WindowContainerTransaction(); t.setAlwaysOnTop(wc.mRemoteToken.toWindowContainerToken(), true); Loading