Merge "Add ActivityWindowInfo into LaunchActivityItem" into main
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ae556c9..22b8d92 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -211,6 +211,7 @@
import android.view.translation.TranslationSpec;
import android.view.translation.UiTranslationSpec;
import android.webkit.WebView;
+import android.window.ActivityWindowInfo;
import android.window.ITaskFragmentOrganizer;
import android.window.SizeConfigurationBuckets;
import android.window.SplashScreen;
@@ -603,6 +604,9 @@
boolean hideForNow;
Configuration createdConfig;
Configuration overrideConfig;
+ @NonNull
+ private ActivityWindowInfo mActivityWindowInfo;
+
// Used for consolidating configs before sending on to Activity.
private final Configuration tmpConfig = new Configuration();
// Callback used for updating activity override config and camera compat control state.
@@ -670,7 +674,8 @@
List<ReferrerIntent> pendingNewIntents, SceneTransitionInfo sceneTransitionInfo,
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
IBinder assistToken, IBinder shareableActivityToken, boolean launchedFromBubble,
- IBinder taskFragmentToken, IBinder initialCallerInfoAccessToken) {
+ IBinder taskFragmentToken, IBinder initialCallerInfoAccessToken,
+ ActivityWindowInfo activityWindowInfo) {
this.token = token;
this.assistToken = assistToken;
this.shareableActivityToken = shareableActivityToken;
@@ -691,6 +696,7 @@
mSceneTransitionInfo = sceneTransitionInfo;
mLaunchedFromBubble = launchedFromBubble;
mTaskFragmentToken = taskFragmentToken;
+ mActivityWindowInfo = activityWindowInfo;
init();
}
@@ -779,6 +785,11 @@
return activity != null && activity.mVisibleFromServer;
}
+ @NonNull
+ public ActivityWindowInfo getActivityWindowInfo() {
+ return mActivityWindowInfo;
+ }
+
public String toString() {
ComponentName componentName = intent != null ? intent.getComponent() : null;
return "ActivityRecord{"
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 95f5ad0..f02cb21 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -42,6 +42,7 @@
import android.os.Parcel;
import android.os.PersistableBundle;
import android.os.Trace;
+import android.window.ActivityWindowInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
@@ -81,6 +82,8 @@
private boolean mLaunchedFromBubble;
private IBinder mTaskFragmentToken;
private IBinder mInitialCallerInfoAccessToken;
+ private ActivityWindowInfo mActivityWindowInfo;
+
/**
* It is only non-null if the process is the first time to launch activity. It is only an
* optimization for quick look up of the interface so the field is ignored for comparison.
@@ -107,7 +110,7 @@
mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mSceneTransitionInfo, mIsForward,
mProfilerInfo, client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
- mTaskFragmentToken, mInitialCallerInfoAccessToken);
+ mTaskFragmentToken, mInitialCallerInfoAccessToken, mActivityWindowInfo);
client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -141,7 +144,8 @@
boolean isForward, @Nullable ProfilerInfo profilerInfo, @NonNull IBinder assistToken,
@Nullable IActivityClientController activityClientController,
@NonNull IBinder shareableActivityToken, boolean launchedFromBubble,
- @Nullable IBinder taskFragmentToken, @NonNull IBinder initialCallerInfoAccessToken) {
+ @Nullable IBinder taskFragmentToken, @NonNull IBinder initialCallerInfoAccessToken,
+ @NonNull ActivityWindowInfo activityWindowInfo) {
LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
if (instance == null) {
instance = new LaunchActivityItem();
@@ -156,7 +160,8 @@
sceneTransitionInfo, isForward,
profilerInfo != null ? new ProfilerInfo(profilerInfo) : null,
assistToken, activityClientController, shareableActivityToken,
- launchedFromBubble, taskFragmentToken, initialCallerInfoAccessToken);
+ launchedFromBubble, taskFragmentToken, initialCallerInfoAccessToken,
+ new ActivityWindowInfo(activityWindowInfo));
return instance;
}
@@ -171,7 +176,7 @@
@Override
public void recycle() {
setValues(this, null, null, 0, null, null, null, 0, null, null, 0, null, null, null, null,
- null, false, null, null, null, null, false, null, null);
+ null, false, null, null, null, null, false, null, null, null);
ObjectPool.recycle(this);
}
@@ -203,6 +208,7 @@
dest.writeBoolean(mLaunchedFromBubble);
dest.writeStrongBinder(mTaskFragmentToken);
dest.writeStrongBinder(mInitialCallerInfoAccessToken);
+ dest.writeTypedObject(mActivityWindowInfo, flags);
}
/** Read from Parcel. */
@@ -223,7 +229,8 @@
in.readStrongBinder(),
in.readBoolean(),
in.readStrongBinder(),
- in.readStrongBinder());
+ in.readStrongBinder(),
+ in.readTypedObject(ActivityWindowInfo.CREATOR));
}
public static final @NonNull Creator<LaunchActivityItem> CREATOR = new Creator<>() {
@@ -264,7 +271,8 @@
&& Objects.equals(mShareableActivityToken, other.mShareableActivityToken)
&& Objects.equals(mTaskFragmentToken, other.mTaskFragmentToken)
&& Objects.equals(mInitialCallerInfoAccessToken,
- other.mInitialCallerInfoAccessToken);
+ other.mInitialCallerInfoAccessToken)
+ && Objects.equals(mActivityWindowInfo, other.mActivityWindowInfo);
}
@Override
@@ -289,6 +297,7 @@
result = 31 * result + Objects.hashCode(mShareableActivityToken);
result = 31 * result + Objects.hashCode(mTaskFragmentToken);
result = 31 * result + Objects.hashCode(mInitialCallerInfoAccessToken);
+ result = 31 * result + Objects.hashCode(mActivityWindowInfo);
return result;
}
@@ -335,7 +344,9 @@
+ ",sceneTransitionInfo=" + mSceneTransitionInfo
+ ",profilerInfo=" + mProfilerInfo
+ ",assistToken=" + mAssistToken
- + ",shareableActivityToken=" + mShareableActivityToken + "}";
+ + ",shareableActivityToken=" + mShareableActivityToken
+ + ",activityWindowInfo=" + mActivityWindowInfo
+ + "}";
}
// Using the same method to set and clear values to make sure we don't forget anything
@@ -351,7 +362,8 @@
@Nullable ProfilerInfo profilerInfo, @Nullable IBinder assistToken,
@Nullable IActivityClientController activityClientController,
@Nullable IBinder shareableActivityToken, boolean launchedFromBubble,
- @Nullable IBinder taskFragmentToken, @Nullable IBinder initialCallerInfoAccessToken) {
+ @Nullable IBinder taskFragmentToken, @Nullable IBinder initialCallerInfoAccessToken,
+ @Nullable ActivityWindowInfo activityWindowInfo) {
instance.mActivityToken = activityToken;
instance.mIntent = intent;
instance.mIdent = ident;
@@ -375,5 +387,6 @@
instance.mLaunchedFromBubble = launchedFromBubble;
instance.mTaskFragmentToken = taskFragmentToken;
instance.mInitialCallerInfoAccessToken = initialCallerInfoAccessToken;
+ instance.mActivityWindowInfo = activityWindowInfo;
}
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index c6447be..207fe73 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -39,6 +39,7 @@
import android.os.IBinder;
import android.os.PersistableBundle;
import android.platform.test.annotations.Presubmit;
+import android.window.ActivityWindowInfo;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -124,6 +125,7 @@
final int deviceId = 3;
final IBinder taskFragmentToken = new Binder();
final IBinder initialCallerInfoAccessToken = new Binder();
+ final ActivityWindowInfo activityWindowInfo = new ActivityWindowInfo();
testRecycle(() -> new LaunchActivityItemBuilder(
activityToken, intent, activityInfo)
@@ -142,6 +144,7 @@
.setTaskFragmentToken(taskFragmentToken)
.setDeviceId(deviceId)
.setInitialCallerInfoAccessToken(initialCallerInfoAccessToken)
+ .setActivityWindowInfo(activityWindowInfo)
.build());
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
index d641659..c1b9efd 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
@@ -32,6 +32,7 @@
import android.os.IBinder;
import android.os.PersistableBundle;
import android.util.MergedConfiguration;
+import android.window.ActivityWindowInfo;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
@@ -134,6 +135,8 @@
private IBinder mTaskFragmentToken;
@Nullable
private IBinder mInitialCallerInfoAccessToken;
+ @NonNull
+ private ActivityWindowInfo mActivityWindowInfo = new ActivityWindowInfo();
LaunchActivityItemBuilder(@NonNull IBinder activityToken, @NonNull Intent intent,
@NonNull ActivityInfo info) {
@@ -260,6 +263,13 @@
}
@NonNull
+ LaunchActivityItemBuilder setActivityWindowInfo(
+ @NonNull ActivityWindowInfo activityWindowInfo) {
+ mActivityWindowInfo.set(activityWindowInfo);
+ return this;
+ }
+
+ @NonNull
LaunchActivityItem build() {
return LaunchActivityItem.obtain(mActivityToken, mIntent, mIdent, mInfo,
mCurConfig, mOverrideConfig, mDeviceId, mReferrer, mVoiceInteractor,
@@ -267,7 +277,7 @@
mActivityOptions != null ? mActivityOptions.getSceneTransitionInfo() : null,
mIsForward, mProfilerInfo, mAssistToken, null /* activityClientController */,
mShareableActivityToken, mLaunchedFromBubble, mTaskFragmentToken,
- mInitialCallerInfoAccessToken);
+ mInitialCallerInfoAccessToken, mActivityWindowInfo);
}
}
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index aa80013..03b85dc 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -32,6 +32,7 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -40,6 +41,7 @@
import android.os.PersistableBundle;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
+import android.window.ActivityWindowInfo;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -180,6 +182,9 @@
bundle.putParcelable("data", new ParcelableData(1));
final PersistableBundle persistableBundle = new PersistableBundle();
persistableBundle.putInt("k", 4);
+ final ActivityWindowInfo activityWindowInfo = new ActivityWindowInfo();
+ activityWindowInfo.set(true /* isEmbedded */, new Rect(0, 0, 500, 1000),
+ new Rect(0, 0, 500, 500));
final LaunchActivityItem item = new LaunchActivityItemBuilder(
activityToken, intent, activityInfo)
@@ -198,6 +203,7 @@
.setShareableActivityToken(new Binder())
.setTaskFragmentToken(new Binder())
.setInitialCallerInfoAccessToken(new Binder())
+ .setActivityWindowInfo(activityWindowInfo)
.build();
writeAndPrepareForReading(item);
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 39cb616..66be05f 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -61,6 +61,7 @@
import android.platform.test.annotations.Presubmit;
import android.testing.PollingCheck;
import android.view.WindowManagerGlobal;
+import android.window.ActivityWindowInfo;
import android.window.SizeConfigurationBuckets;
import androidx.test.annotation.UiThreadTest;
@@ -354,7 +355,7 @@
null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
mThread /* client */, null /* asssitToken */, null /* shareableActivityToken */,
false /* launchedFromBubble */, null /* taskfragmentToken */,
- null /* initialCallerInfoAccessToken */);
+ null /* initialCallerInfoAccessToken */, new ActivityWindowInfo());
}
@Override
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index b2e5b75..ae3a854 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -72,6 +72,7 @@
import android.util.Size;
import android.util.SparseArray;
import android.view.WindowMetrics;
+import android.window.ActivityWindowInfo;
import android.window.TaskFragmentAnimationParams;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentOperation;
@@ -2864,11 +2865,27 @@
*/
@Override
public boolean isActivityEmbedded(@NonNull Activity activity) {
+ Objects.requireNonNull(activity);
synchronized (mLock) {
+ if (Flags.activityWindowInfoFlag()) {
+ final ActivityWindowInfo activityWindowInfo = getActivityWindowInfo(activity);
+ return activityWindowInfo != null && activityWindowInfo.isEmbedded();
+ }
return mPresenter.isActivityEmbedded(activity.getActivityToken());
}
}
+ @Nullable
+ private static ActivityWindowInfo getActivityWindowInfo(@NonNull Activity activity) {
+ if (activity.isFinishing()) {
+ return null;
+ }
+ final ActivityThread.ActivityClientRecord record =
+ ActivityThread.currentActivityThread()
+ .getActivityClient(activity.getActivityToken());
+ return record != null ? record.getActivityWindowInfo() : null;
+ }
+
/**
* If the two rules have the same presentation, and the calculated {@link SplitAttributes}
* matches the {@link SplitAttributes} of {@link SplitContainer}, we can reuse the same
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index bc6f93f..d60fe4b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -353,6 +353,7 @@
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
+import android.window.ActivityWindowInfo;
import android.window.ITaskFragmentOrganizer;
import android.window.RemoteTransition;
import android.window.SizeConfigurationBuckets;
@@ -519,6 +520,7 @@
private int mLastReportedDisplayId;
boolean mLastReportedMultiWindowMode;
boolean mLastReportedPictureInPictureMode;
+ private final ActivityWindowInfo mLastReportedActivityWindowInfo = new ActivityWindowInfo();
ActivityRecord resultTo; // who started this entry, so will get our reply
final String resultWho; // additional identifier for use by resultTo.
final int requestCode; // code given by requester (resultTo)
@@ -958,6 +960,7 @@
*/
private final Configuration mTmpConfig = new Configuration();
private final Rect mTmpBounds = new Rect();
+ private final ActivityWindowInfo mTmpActivityWindowInfo = new ActivityWindowInfo();
// Token for targeting this activity for assist purposes.
final Binder assistToken = new Binder();
@@ -1096,6 +1099,12 @@
pw.println(prefix + "mLastReportedConfigurations:");
mLastReportedConfiguration.dump(pw, prefix + " ");
+ if (Flags.activityWindowInfoFlag()) {
+ pw.print(prefix);
+ pw.print("mLastReportedActivityWindowInfo=");
+ pw.println(mLastReportedActivityWindowInfo);
+ }
+
pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
pw.println(prefix + "RequestedOverrideConfiguration="
@@ -3150,6 +3159,30 @@
}
}
+ /**
+ * This is different from {@link #isEmbedded()}.
+ * {@link #isEmbedded()} is {@code true} when any of the parent {@link TaskFragment} is created
+ * by a {@link android.window.TaskFragmentOrganizer}, while this method is {@code true} when
+ * the parent {@link TaskFragment} is embedded and has bounds override that does not fill the
+ * leaf {@link Task}.
+ */
+ boolean isEmbeddedInHostContainer() {
+ final TaskFragment taskFragment = getOrganizedTaskFragment();
+ return taskFragment != null && taskFragment.isEmbeddedWithBoundsOverride();
+ }
+
+ @NonNull
+ ActivityWindowInfo getActivityWindowInfo() {
+ if (!Flags.activityWindowInfoFlag() || !isAttached()) {
+ return mTmpActivityWindowInfo;
+ }
+ mTmpActivityWindowInfo.set(
+ isEmbeddedInHostContainer(),
+ getTask().getBounds(),
+ getTaskFragment().getBounds());
+ return mTmpActivityWindowInfo;
+ }
+
@Override
@Nullable
TaskDisplayArea getDisplayArea() {
@@ -8213,6 +8246,12 @@
mLastReportedConfiguration.setConfiguration(global, override);
}
+ void setLastReportedActivityWindowInfo(@NonNull ActivityWindowInfo activityWindowInfo) {
+ if (Flags.activityWindowInfoFlag()) {
+ mLastReportedActivityWindowInfo.set(activityWindowInfo);
+ }
+ }
+
@Nullable
CompatDisplayInsets getCompatDisplayInsets() {
if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 09f5eda..e0faddf 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -138,6 +138,7 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.Display;
+import android.window.ActivityWindowInfo;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -909,6 +910,9 @@
final Configuration overrideConfig = r.getMergedOverrideConfiguration();
r.setLastReportedConfiguration(procConfig, overrideConfig);
+ final ActivityWindowInfo activityWindowInfo = r.getActivityWindowInfo();
+ r.setLastReportedActivityWindowInfo(activityWindowInfo);
+
logIfTransactionTooLarge(r.intent, r.getSavedState());
final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment();
@@ -931,7 +935,7 @@
results, newIntents, r.takeSceneTransitionInfo(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken,
- r.initialCallerInfoAccessToken);
+ r.initialCallerInfoAccessToken, activityWindowInfo);
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index 8d054db..24b533a 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -1197,16 +1197,13 @@
}
}
- // TODO(b/204399167): change to push the embedded state to the client side
@Override
public boolean isActivityEmbedded(IBinder activityToken) {
synchronized (mGlobalLock) {
final ActivityRecord activity = ActivityRecord.forTokenLocked(activityToken);
- if (activity == null) {
- return false;
- }
- final TaskFragment taskFragment = activity.getOrganizedTaskFragment();
- return taskFragment != null && taskFragment.isEmbeddedWithBoundsOverride();
+ return activity != null
+ ? activity.isEmbeddedInHostContainer()
+ : false;
}
}