summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Riddle Hsu <riddlehsu@google.com> 2020-05-12 09:05:17 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-05-12 09:05:17 +0000
commit8e726a2ef72965430f514b0d8fa17a01798e51dc (patch)
tree89e98a59b3571079dbe40836edc46d59f0eea904
parent80dcec801deb24186ce375da85c5b96bc2437038 (diff)
parentd490c57905bc47a4d583d69049864e6348171c61 (diff)
Merge changes from topic "b147213487" into rvc-dev
* changes: Send fixed rotation adjustments to the associated client Add support to override display adjustments by token Add fixed rotation display adjustments
-rw-r--r--core/java/android/app/Activity.java5
-rw-r--r--core/java/android/app/ActivityThread.java60
-rw-r--r--core/java/android/app/ClientTransactionHandler.java5
-rw-r--r--core/java/android/app/ResourcesManager.java30
-rw-r--r--core/java/android/app/servertransaction/FixedRotationAdjustmentsItem.java112
-rw-r--r--core/java/android/app/servertransaction/LaunchActivityItem.java24
-rw-r--r--core/java/android/content/res/Resources.java35
-rw-r--r--core/java/android/view/Display.java32
-rw-r--r--core/java/android/view/DisplayAdjustments.java152
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java8
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java2
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java24
-rw-r--r--core/tests/coretests/src/android/content/res/ResourcesManagerTest.java31
-rw-r--r--core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java37
-rw-r--r--core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java59
17 files changed, 598 insertions, 23 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index b2976eca9590..af5fafbc93d4 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7151,6 +7151,11 @@ public class Activity extends ContextThemeWrapper
writer.println(mChangingConfigurations);
writer.print(innerPrefix); writer.print("mCurrentConfig=");
writer.println(mCurrentConfig);
+ if (getResources().hasOverrideDisplayAdjustments()) {
+ writer.print(innerPrefix);
+ writer.print("FixedRotationAdjustments=");
+ writer.println(getResources().getDisplayAdjustments().getFixedRotationAdjustments());
+ }
mFragments.dumpLoaders(innerPrefix, fd, writer, args);
mFragments.getFragmentManager().dump(innerPrefix, fd, writer, args);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b45705924910..c75870e933f8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -156,6 +156,8 @@ import android.util.proto.ProtoOutputStream;
import android.view.Choreographer;
import android.view.ContextThemeWrapper;
import android.view.Display;
+import android.view.DisplayAdjustments;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewDebug;
@@ -215,6 +217,7 @@ import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
final class RemoteServiceException extends AndroidRuntimeException {
public RemoteServiceException(String msg) {
@@ -405,6 +408,9 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final ResourcesManager mResourcesManager;
+ /** The active adjustments that override the {@link DisplayAdjustments} in resources. */
+ private ArrayList<Pair<IBinder, Consumer<DisplayAdjustments>>> mActiveRotationAdjustments;
+
// Registry of remote cancellation transports pending a reply with reply handles.
@GuardedBy("this")
private @Nullable Map<SafeCancellationTransport, CancellationSignal> mRemoteCancellations;
@@ -541,6 +547,12 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage
boolean mPreserveWindow;
+ /**
+ * If non-null, the activity is launching with a specified rotation, the adjustments should
+ * be consumed before activity creation.
+ */
+ FixedRotationAdjustments mPendingFixedRotationAdjustments;
+
@LifecycleState
private int mLifecycleState = PRE_ON_CREATE;
@@ -557,7 +569,7 @@ public final class ActivityThread extends ClientTransactionHandler {
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, boolean isForward,
ProfilerInfo profilerInfo, ClientTransactionHandler client,
- IBinder assistToken) {
+ IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
this.token = token;
this.assistToken = assistToken;
this.ident = ident;
@@ -575,6 +587,7 @@ public final class ActivityThread extends ClientTransactionHandler {
this.overrideConfig = overrideConfig;
this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo,
compatInfo);
+ mPendingFixedRotationAdjustments = fixedRotationAdjustments;
init();
}
@@ -3233,6 +3246,44 @@ public final class ActivityThread extends ClientTransactionHandler {
sendMessage(H.CLEAN_UP_CONTEXT, cci);
}
+ @Override
+ public void handleFixedRotationAdjustments(@NonNull IBinder token,
+ @Nullable FixedRotationAdjustments fixedRotationAdjustments) {
+ final Consumer<DisplayAdjustments> override = fixedRotationAdjustments != null
+ ? displayAdjustments -> displayAdjustments.setFixedRotationAdjustments(
+ fixedRotationAdjustments)
+ : null;
+ if (!mResourcesManager.overrideTokenDisplayAdjustments(token, override)) {
+ // No resources are associated with the token.
+ return;
+ }
+ if (mActivities.get(token) == null) {
+ // Only apply the override to application for activity token because the appearance of
+ // activity is usually more sensitive to the application resources.
+ return;
+ }
+
+ // Apply the last override to application resources for compatibility. Because the Resources
+ // of Display can be from application, e.g.
+ // applicationContext.getSystemService(DisplayManager.class).getDisplay(displayId)
+ // and the deprecated usage:
+ // applicationContext.getSystemService(WindowManager.class).getDefaultDisplay();
+ final Consumer<DisplayAdjustments> appOverride;
+ if (mActiveRotationAdjustments == null) {
+ mActiveRotationAdjustments = new ArrayList<>(2);
+ }
+ if (override != null) {
+ mActiveRotationAdjustments.add(Pair.create(token, override));
+ appOverride = override;
+ } else {
+ mActiveRotationAdjustments.removeIf(adjustmentsPair -> adjustmentsPair.first == token);
+ appOverride = mActiveRotationAdjustments.isEmpty()
+ ? null
+ : mActiveRotationAdjustments.get(mActiveRotationAdjustments.size() - 1).second;
+ }
+ mInitialApplication.getResources().overrideDisplayAdjustments(appOverride);
+ }
+
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
@@ -3446,6 +3497,13 @@ public final class ActivityThread extends ClientTransactionHandler {
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
+ // The rotation adjustments must be applied before creating the activity, so the activity
+ // can get the adjusted display info during creation.
+ if (r.mPendingFixedRotationAdjustments != null) {
+ handleFixedRotationAdjustments(r.token, r.mPendingFixedRotationAdjustments);
+ r.mPendingFixedRotationAdjustments = null;
+ }
+
final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
// For debugging purposes, if the activity's package name contains the value of
// the "debug.use-second-display" system property as a substring, then show
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 83465b0f8d36..2df756e80fde 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -25,6 +25,7 @@ import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.IBinder;
import android.util.MergedConfiguration;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
@@ -167,6 +168,10 @@ public abstract class ClientTransactionHandler {
/** Deliver app configuration change notification. */
public abstract void handleConfigurationChanged(Configuration config);
+ /** Apply addition adjustments to override display information. */
+ public abstract void handleFixedRotationAdjustments(IBinder token,
+ FixedRotationAdjustments fixedRotationAdjustments);
+
/**
* Get {@link android.app.ActivityThread.ActivityClientRecord} instance that corresponds to the
* provided token.
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 106f8ac92d05..1aae04db32d0 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -59,6 +59,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.WeakHashMap;
+import java.util.function.Consumer;
import java.util.function.Predicate;
/** @hide */
@@ -1296,6 +1297,35 @@ public class ResourcesManager {
}
}
+ /**
+ * Overrides the display adjustments of all resources which are associated with the given token.
+ *
+ * @param token The token that owns the resources.
+ * @param override The operation to override the existing display adjustments. If it is null,
+ * the override adjustments will be cleared.
+ * @return {@code true} if the override takes effect.
+ */
+ public boolean overrideTokenDisplayAdjustments(IBinder token,
+ @Nullable Consumer<DisplayAdjustments> override) {
+ boolean handled = false;
+ synchronized (this) {
+ final ActivityResources tokenResources = mActivityResourceReferences.get(token);
+ if (tokenResources == null) {
+ return false;
+ }
+ final ArrayList<WeakReference<Resources>> resourcesRefs =
+ tokenResources.activityResources;
+ for (int i = resourcesRefs.size() - 1; i >= 0; i--) {
+ final Resources res = resourcesRefs.get(i).get();
+ if (res != null) {
+ res.overrideDisplayAdjustments(override);
+ handled = true;
+ }
+ }
+ }
+ return handled;
+ }
+
private class UpdateHandler implements Resources.UpdateCallbacks {
/**
diff --git a/core/java/android/app/servertransaction/FixedRotationAdjustmentsItem.java b/core/java/android/app/servertransaction/FixedRotationAdjustmentsItem.java
new file mode 100644
index 000000000000..6183d5f28fdb
--- /dev/null
+++ b/core/java/android/app/servertransaction/FixedRotationAdjustmentsItem.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.servertransaction;
+
+import android.app.ClientTransactionHandler;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
+
+import java.util.Objects;
+
+/**
+ * The request to update display adjustments for a rotated activity or window token.
+ * @hide
+ */
+public class FixedRotationAdjustmentsItem extends ClientTransactionItem {
+
+ /** The token who may have {@link android.content.res.Resources}. */
+ private IBinder mToken;
+
+ /**
+ * The adjustments for the display adjustments of resources. If it is null, the existing
+ * rotation adjustments will be dropped to restore natural state.
+ */
+ private FixedRotationAdjustments mFixedRotationAdjustments;
+
+ private FixedRotationAdjustmentsItem() {}
+
+ /** Obtain an instance initialized with provided params. */
+ public static FixedRotationAdjustmentsItem obtain(IBinder token,
+ FixedRotationAdjustments fixedRotationAdjustments) {
+ FixedRotationAdjustmentsItem instance =
+ ObjectPool.obtain(FixedRotationAdjustmentsItem.class);
+ if (instance == null) {
+ instance = new FixedRotationAdjustmentsItem();
+ }
+ instance.mToken = token;
+ instance.mFixedRotationAdjustments = fixedRotationAdjustments;
+
+ return instance;
+ }
+
+ @Override
+ public void execute(ClientTransactionHandler client, IBinder token,
+ PendingTransactionActions pendingActions) {
+ client.handleFixedRotationAdjustments(mToken, mFixedRotationAdjustments);
+ }
+
+ @Override
+ public void recycle() {
+ mToken = null;
+ mFixedRotationAdjustments = null;
+ ObjectPool.recycle(this);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStrongBinder(mToken);
+ dest.writeTypedObject(mFixedRotationAdjustments, flags);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final FixedRotationAdjustmentsItem other = (FixedRotationAdjustmentsItem) o;
+ return Objects.equals(mToken, other.mToken)
+ && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + Objects.hashCode(mToken);
+ result = 31 * result + Objects.hashCode(mFixedRotationAdjustments);
+ return result;
+ }
+
+ private FixedRotationAdjustmentsItem(Parcel in) {
+ mToken = in.readStrongBinder();
+ mFixedRotationAdjustments = in.readTypedObject(FixedRotationAdjustments.CREATOR);
+ }
+
+ public static final Creator<FixedRotationAdjustmentsItem> CREATOR =
+ new Creator<FixedRotationAdjustmentsItem>() {
+ public FixedRotationAdjustmentsItem createFromParcel(Parcel in) {
+ return new FixedRotationAdjustmentsItem(in);
+ }
+
+ public FixedRotationAdjustmentsItem[] newArray(int size) {
+ return new FixedRotationAdjustmentsItem[size];
+ }
+ };
+}
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 9ab6e7fc9f58..2e7b6262c785 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -33,6 +33,7 @@ import android.os.IBinder;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.os.Trace;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
@@ -64,6 +65,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
private boolean mIsForward;
private ProfilerInfo mProfilerInfo;
private IBinder mAssistToken;
+ private FixedRotationAdjustments mFixedRotationAdjustments;
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
@@ -79,7 +81,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
- mProfilerInfo, client, mAssistToken);
+ mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -101,14 +103,14 @@ public class LaunchActivityItem extends ClientTransactionItem {
String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo,
- IBinder assistToken) {
+ IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
if (instance == null) {
instance = new LaunchActivityItem();
}
setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
voiceInteractor, procState, state, persistentState, pendingResults,
- pendingNewIntents, isForward, profilerInfo, assistToken);
+ pendingNewIntents, isForward, profilerInfo, assistToken, fixedRotationAdjustments);
return instance;
}
@@ -116,7 +118,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
@Override
public void recycle() {
setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
- false, null, null);
+ false, null, null, null);
ObjectPool.recycle(this);
}
@@ -142,6 +144,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
dest.writeBoolean(mIsForward);
dest.writeTypedObject(mProfilerInfo, flags);
dest.writeStrongBinder(mAssistToken);
+ dest.writeTypedObject(mFixedRotationAdjustments, flags);
}
/** Read from Parcel. */
@@ -156,7 +159,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
in.createTypedArrayList(ResultInfo.CREATOR),
in.createTypedArrayList(ReferrerIntent.CREATOR), in.readBoolean(),
in.readTypedObject(ProfilerInfo.CREATOR),
- in.readStrongBinder());
+ in.readStrongBinder(),
+ in.readTypedObject(FixedRotationAdjustments.CREATOR));
}
public static final @android.annotation.NonNull Creator<LaunchActivityItem> CREATOR =
@@ -192,7 +196,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
&& Objects.equals(mPendingNewIntents, other.mPendingNewIntents)
&& mIsForward == other.mIsForward
&& Objects.equals(mProfilerInfo, other.mProfilerInfo)
- && Objects.equals(mAssistToken, other.mAssistToken);
+ && Objects.equals(mAssistToken, other.mAssistToken)
+ && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments);
}
@Override
@@ -212,6 +217,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
result = 31 * result + (mIsForward ? 1 : 0);
result = 31 * result + Objects.hashCode(mProfilerInfo);
result = 31 * result + Objects.hashCode(mAssistToken);
+ result = 31 * result + Objects.hashCode(mFixedRotationAdjustments);
return result;
}
@@ -247,7 +253,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
+ ",referrer=" + mReferrer + ",procState=" + mProcState + ",state=" + mState
+ ",persistentState=" + mPersistentState + ",pendingResults=" + mPendingResults
+ ",pendingNewIntents=" + mPendingNewIntents + ",profilerInfo=" + mProfilerInfo
- + " assistToken=" + mAssistToken
+ + ",assistToken=" + mAssistToken + ",rotationAdj=" + mFixedRotationAdjustments
+ "}";
}
@@ -257,7 +263,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
- boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken) {
+ boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
+ FixedRotationAdjustments fixedRotationAdjustments) {
instance.mIntent = intent;
instance.mIdent = ident;
instance.mInfo = info;
@@ -274,5 +281,6 @@ public class LaunchActivityItem extends ClientTransactionItem {
instance.mIsForward = isForward;
instance.mProfilerInfo = profilerInfo;
instance.mAssistToken = assistToken;
+ instance.mFixedRotationAdjustments = fixedRotationAdjustments;
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c399bc72e438..0f1c876a1133 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -81,6 +81,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.function.Consumer;
/**
* Class for accessing an application's resources. This sits on top of the
@@ -140,6 +141,9 @@ public class Resources {
@UnsupportedAppUsage
private DrawableInflater mDrawableInflater;
+ /** Used to override the returned adjustments of {@link #getDisplayAdjustments}. */
+ private DisplayAdjustments mOverrideDisplayAdjustments;
+
/** Lock object used to protect access to {@link #mTmpValue}. */
private final Object mTmpValueLock = new Object();
@@ -2055,10 +2059,41 @@ public class Resources {
/** @hide */
@UnsupportedAppUsage
public DisplayAdjustments getDisplayAdjustments() {
+ final DisplayAdjustments overrideDisplayAdjustments = mOverrideDisplayAdjustments;
+ if (overrideDisplayAdjustments != null) {
+ return overrideDisplayAdjustments;
+ }
return mResourcesImpl.getDisplayAdjustments();
}
/**
+ * Customize the display adjustments based on the current one in {@link #mResourcesImpl}, in
+ * order to isolate the effect with other instances of {@link Resource} that may share the same
+ * instance of {@link ResourcesImpl}.
+ *
+ * @param override The operation to override the existing display adjustments. If it is null,
+ * the override adjustments will be cleared.
+ * @hide
+ */
+ public void overrideDisplayAdjustments(@Nullable Consumer<DisplayAdjustments> override) {
+ if (override != null) {
+ mOverrideDisplayAdjustments = new DisplayAdjustments(
+ mResourcesImpl.getDisplayAdjustments());
+ override.accept(mOverrideDisplayAdjustments);
+ } else {
+ mOverrideDisplayAdjustments = null;
+ }
+ }
+
+ /**
+ * Return {@code true} if the override display adjustments have been set.
+ * @hide
+ */
+ public boolean hasOverrideDisplayAdjustments() {
+ return mOverrideDisplayAdjustments != null;
+ }
+
+ /**
* Return the current configuration that is in effect for this resource
* object. The returned object should be treated as read-only.
*
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 4469fdbb12ec..8db1703a627f 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -104,6 +104,14 @@ public final class Display {
private int mCachedAppHeightCompat;
/**
+ * Indicates that the application is started in a different rotation than the real display, so
+ * the display information may be adjusted. That ensures the methods {@link #getRotation},
+ * {@link #getRealSize}, {@link #getRealMetrics}, and {@link #getCutout} are consistent with how
+ * the application window is laid out.
+ */
+ private boolean mMayAdjustByFixedRotation;
+
+ /**
* The default Display id, which is the id of the primary display assuming there is one.
*/
public static final int DEFAULT_DISPLAY = 0;
@@ -804,7 +812,9 @@ public final class Display {
public int getRotation() {
synchronized (this) {
updateDisplayInfoLocked();
- return mDisplayInfo.rotation;
+ return mMayAdjustByFixedRotation
+ ? getDisplayAdjustments().getRotation(mDisplayInfo.rotation)
+ : mDisplayInfo.rotation;
}
}
@@ -828,7 +838,9 @@ public final class Display {
public DisplayCutout getCutout() {
synchronized (this) {
updateDisplayInfoLocked();
- return mDisplayInfo.displayCutout;
+ return mMayAdjustByFixedRotation
+ ? getDisplayAdjustments().getDisplayCutout(mDisplayInfo.displayCutout)
+ : mDisplayInfo.displayCutout;
}
}
@@ -1140,6 +1152,9 @@ public final class Display {
updateDisplayInfoLocked();
outSize.x = mDisplayInfo.logicalWidth;
outSize.y = mDisplayInfo.logicalHeight;
+ if (mMayAdjustByFixedRotation) {
+ getDisplayAdjustments().adjustSize(outSize, mDisplayInfo.rotation);
+ }
}
}
@@ -1159,6 +1174,9 @@ public final class Display {
updateDisplayInfoLocked();
mDisplayInfo.getLogicalMetrics(outMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+ if (mMayAdjustByFixedRotation) {
+ getDisplayAdjustments().adjustMetrics(outMetrics, mDisplayInfo.rotation);
+ }
}
}
@@ -1225,6 +1243,9 @@ public final class Display {
}
}
}
+
+ mMayAdjustByFixedRotation = mResources != null
+ && mResources.hasOverrideDisplayAdjustments();
}
private void updateCachedAppSizeIfNeededLocked() {
@@ -1243,9 +1264,12 @@ public final class Display {
public String toString() {
synchronized (this) {
updateDisplayInfoLocked();
- mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
+ final DisplayAdjustments adjustments = getDisplayAdjustments();
+ mDisplayInfo.getAppMetrics(mTempMetrics, adjustments);
return "Display id " + mDisplayId + ": " + mDisplayInfo
- + ", " + mTempMetrics + ", isValid=" + mIsValid;
+ + (mMayAdjustByFixedRotation
+ ? (", " + adjustments.getFixedRotationAdjustments() + ", ") : ", ")
+ + mTempMetrics + ", isValid=" + mIsValid;
}
}
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
index 27c2d5c5cdc3..c726bee9f402 100644
--- a/core/java/android/view/DisplayAdjustments.java
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -21,6 +21,10 @@ import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.DisplayMetrics;
import java.util.Objects;
@@ -30,6 +34,7 @@ public class DisplayAdjustments {
private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
private final Configuration mConfiguration = new Configuration(Configuration.EMPTY);
+ private FixedRotationAdjustments mFixedRotationAdjustments;
@UnsupportedAppUsage
public DisplayAdjustments() {
@@ -44,6 +49,7 @@ public class DisplayAdjustments {
public DisplayAdjustments(@NonNull DisplayAdjustments daj) {
setCompatibilityInfo(daj.mCompatInfo);
mConfiguration.setTo(daj.getConfiguration());
+ mFixedRotationAdjustments = daj.mFixedRotationAdjustments;
}
@UnsupportedAppUsage
@@ -84,11 +90,78 @@ public class DisplayAdjustments {
return mConfiguration;
}
+ public void setFixedRotationAdjustments(FixedRotationAdjustments fixedRotationAdjustments) {
+ mFixedRotationAdjustments = fixedRotationAdjustments;
+ }
+
+ public FixedRotationAdjustments getFixedRotationAdjustments() {
+ return mFixedRotationAdjustments;
+ }
+
+ /** Returns {@code false} if the width and height of display should swap. */
+ private boolean noFlip(@Surface.Rotation int realRotation) {
+ final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
+ if (rotationAdjustments == null) {
+ return true;
+ }
+ // Check if the delta is rotated by 90 degrees.
+ return (realRotation - rotationAdjustments.mRotation + 4) % 2 == 0;
+ }
+
+ /** Adjusts the given size if possible. */
+ public void adjustSize(@NonNull Point size, @Surface.Rotation int realRotation) {
+ if (noFlip(realRotation)) {
+ return;
+ }
+ final int w = size.x;
+ size.x = size.y;
+ size.y = w;
+ }
+
+ /** Adjusts the given metrics if possible. */
+ public void adjustMetrics(@NonNull DisplayMetrics metrics, @Surface.Rotation int realRotation) {
+ if (noFlip(realRotation)) {
+ return;
+ }
+ int w = metrics.widthPixels;
+ metrics.widthPixels = metrics.heightPixels;
+ metrics.heightPixels = w;
+
+ w = metrics.noncompatWidthPixels;
+ metrics.noncompatWidthPixels = metrics.noncompatHeightPixels;
+ metrics.noncompatHeightPixels = w;
+
+ float x = metrics.xdpi;
+ metrics.xdpi = metrics.ydpi;
+ metrics.ydpi = x;
+
+ x = metrics.noncompatXdpi;
+ metrics.noncompatXdpi = metrics.noncompatYdpi;
+ metrics.noncompatYdpi = x;
+ }
+
+ /** Returns the adjusted cutout if available. Otherwise the original cutout is returned. */
+ @Nullable
+ public DisplayCutout getDisplayCutout(@Nullable DisplayCutout realCutout) {
+ final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
+ return rotationAdjustments != null && rotationAdjustments.mRotatedDisplayCutout != null
+ ? rotationAdjustments.mRotatedDisplayCutout
+ : realCutout;
+ }
+
+ /** Returns the adjusted rotation if available. Otherwise the original rotation is returned. */
+ @Surface.Rotation
+ public int getRotation(@Surface.Rotation int realRotation) {
+ final FixedRotationAdjustments rotationAdjustments = mFixedRotationAdjustments;
+ return rotationAdjustments != null ? rotationAdjustments.mRotation : realRotation;
+ }
+
@Override
public int hashCode() {
int hash = 17;
hash = hash * 31 + Objects.hashCode(mCompatInfo);
hash = hash * 31 + Objects.hashCode(mConfiguration);
+ hash = hash * 31 + Objects.hashCode(mFixedRotationAdjustments);
return hash;
}
@@ -98,7 +171,82 @@ public class DisplayAdjustments {
return false;
}
DisplayAdjustments daj = (DisplayAdjustments)o;
- return Objects.equals(daj.mCompatInfo, mCompatInfo) &&
- Objects.equals(daj.mConfiguration, mConfiguration);
+ return Objects.equals(daj.mCompatInfo, mCompatInfo)
+ && Objects.equals(daj.mConfiguration, mConfiguration)
+ && Objects.equals(daj.mFixedRotationAdjustments, mFixedRotationAdjustments);
+ }
+
+ /**
+ * An application can be launched in different rotation than the real display. This class
+ * provides the information to adjust the values returned by {@link #Display}.
+ * @hide
+ */
+ public static class FixedRotationAdjustments implements Parcelable {
+ /** The application-based rotation. */
+ @Surface.Rotation
+ final int mRotation;
+
+ /** Non-null if the device has cutout. */
+ @Nullable
+ final DisplayCutout mRotatedDisplayCutout;
+
+ public FixedRotationAdjustments(@Surface.Rotation int rotation, DisplayCutout cutout) {
+ mRotation = rotation;
+ mRotatedDisplayCutout = cutout;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 17;
+ hash = hash * 31 + mRotation;
+ hash = hash * 31 + Objects.hashCode(mRotatedDisplayCutout);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof FixedRotationAdjustments)) {
+ return false;
+ }
+ final FixedRotationAdjustments other = (FixedRotationAdjustments) o;
+ return mRotation == other.mRotation
+ && Objects.equals(mRotatedDisplayCutout, other.mRotatedDisplayCutout);
+ }
+
+ @Override
+ public String toString() {
+ return "FixedRotationAdjustments{rotation=" + Surface.rotationToString(mRotation)
+ + " cutout=" + mRotatedDisplayCutout + "}";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mRotation);
+ dest.writeTypedObject(
+ new DisplayCutout.ParcelableWrapper(mRotatedDisplayCutout), flags);
+ }
+
+ private FixedRotationAdjustments(Parcel in) {
+ mRotation = in.readInt();
+ final DisplayCutout.ParcelableWrapper cutoutWrapper =
+ in.readTypedObject(DisplayCutout.ParcelableWrapper.CREATOR);
+ mRotatedDisplayCutout = cutoutWrapper != null ? cutoutWrapper.get() : null;
+ }
+
+ public static final Creator<FixedRotationAdjustments> CREATOR =
+ new Creator<FixedRotationAdjustments>() {
+ public FixedRotationAdjustments createFromParcel(Parcel in) {
+ return new FixedRotationAdjustments(in);
+ }
+
+ public FixedRotationAdjustments[] newArray(int size) {
+ return new FixedRotationAdjustments[size];
+ }
+ };
}
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index 107fe3f3ced5..6c23125aaf13 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -144,11 +144,12 @@ public class ObjectPoolTests {
IBinder assistToken = new Binder();
LaunchActivityItem emptyItem = LaunchActivityItem.obtain(null, 0, null, null, null, null,
- null, null, 0, null, null, null, null, false, null, null);
+ null, null, 0, null, null, null, null, false, null, null, null);
LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo,
config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
- true /* isForward */, null /* profilerInfo */, assistToken);
+ true /* isForward */, null /* profilerInfo */, assistToken,
+ null /* fixedRotationAdjustments */);
assertNotSame(item, emptyItem);
assertFalse(item.equals(emptyItem));
@@ -158,7 +159,8 @@ public class ObjectPoolTests {
LaunchActivityItem item2 = LaunchActivityItem.obtain(intent, ident, activityInfo,
config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
- true /* isForward */, null /* profilerInfo */, assistToken);
+ true /* isForward */, null /* profilerInfo */, assistToken,
+ null /* fixedRotationAdjustments */);
assertSame(item, item2);
assertFalse(item2.equals(emptyItem));
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index 09ea1b1865c0..3c32c71cf961 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -267,7 +267,7 @@ public class TransactionExecutorTests {
null /* voiceInteractor */, 0 /* procState */, null /* state */,
null /* persistentState */, null /* pendingResults */,
null /* pendingNewIntents */, false /* isForward */, null /* profilerInfo */,
- null /* assistToken*/));
+ null /* assistToken */, null /* fixedRotationAdjustments */));
launchTransaction.addCallback(launchItem);
mExecutor.execute(launchTransaction);
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 47f9323a95f9..3f8d9ef964db 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -52,6 +52,9 @@ import android.os.PersistableBundle;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
+import android.view.DisplayCutout;
+import android.view.Surface;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -187,11 +190,14 @@ public class TransactionParcelTests {
bundle.putParcelable("data", new ParcelableData(1));
PersistableBundle persistableBundle = new PersistableBundle();
persistableBundle.putInt("k", 4);
+ FixedRotationAdjustments fixedRotationAdjustments = new FixedRotationAdjustments(
+ Surface.ROTATION_90, DisplayCutout.NO_CUTOUT);
LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo,
config(), overrideConfig, compat, referrer, null /* voiceInteractor */,
procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(),
- true /* isForward */, null /* profilerInfo */, new Binder());
+ true /* isForward */, null /* profilerInfo */, new Binder(),
+ fixedRotationAdjustments);
writeAndPrepareForReading(item);
// Read from parcel and assert
@@ -340,6 +346,22 @@ public class TransactionParcelTests {
assertTrue(transaction.equals(result));
}
+ @Test
+ public void testFixedRotationAdjustments() {
+ ClientTransaction transaction = ClientTransaction.obtain(new StubAppThread(),
+ null /* activityToken */);
+ transaction.addCallback(FixedRotationAdjustmentsItem.obtain(new Binder(),
+ new FixedRotationAdjustments(Surface.ROTATION_270, DisplayCutout.NO_CUTOUT)));
+
+ writeAndPrepareForReading(transaction);
+
+ // Read from parcel and assert
+ ClientTransaction result = ClientTransaction.CREATOR.createFromParcel(mParcel);
+
+ assertEquals(transaction.hashCode(), result.hashCode());
+ assertTrue(transaction.equals(result));
+ }
+
/** Write to {@link #mParcel} and reset its position to prepare for reading from the start. */
private void writeAndPrepareForReading(Parcelable parcelable) {
parcelable.writeToParcel(mParcel, 0 /* flags */);
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
index 4114b28a7252..efcd458e19cc 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -259,4 +259,35 @@ public class ResourcesManagerTest extends TestCase {
expectedConfig2.orientation = Configuration.ORIENTATION_LANDSCAPE;
assertEquals(expectedConfig2, resources2.getConfiguration());
}
+
+ @SmallTest
+ public void testOverrideDisplayAdjustments() {
+ final int originalOverrideDensity = 200;
+ final int overrideDisplayDensity = 400;
+ final Binder token = new Binder();
+ final Configuration overrideConfig = new Configuration();
+ overrideConfig.densityDpi = originalOverrideDensity;
+ final Resources resources = mResourcesManager.createBaseTokenResources(
+ token, APP_ONE_RES_DIR, null /* splitResDirs */, null /* overlayDirs */,
+ null /* libDirs */, Display.DEFAULT_DISPLAY, overrideConfig,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null /* classLoader */,
+ null /* loaders */);
+
+ // Update the override.
+ boolean handled = mResourcesManager.overrideTokenDisplayAdjustments(token,
+ adjustments -> adjustments.getConfiguration().densityDpi = overrideDisplayDensity);
+
+ assertTrue(handled);
+ assertTrue(resources.hasOverrideDisplayAdjustments());
+ assertEquals(overrideDisplayDensity,
+ resources.getDisplayAdjustments().getConfiguration().densityDpi);
+
+ // Clear the override.
+ handled = mResourcesManager.overrideTokenDisplayAdjustments(token, null /* override */);
+
+ assertTrue(handled);
+ assertFalse(resources.hasOverrideDisplayAdjustments());
+ assertEquals(originalOverrideDensity,
+ resources.getDisplayAdjustments().getConfiguration().densityDpi);
+ }
}
diff --git a/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java b/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java
index afbf8db3cd2d..2fc42e91a8cc 100644
--- a/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java
+++ b/core/tests/coretests/src/android/view/DisplayAdjustmentsTests.java
@@ -19,6 +19,9 @@ package android.view;
import static org.junit.Assert.assertEquals;
import android.content.res.Configuration;
+import android.graphics.Point;
+import android.util.DisplayMetrics;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -67,4 +70,38 @@ public class DisplayAdjustmentsTests {
assertEquals(configuration, newAdjustments.getConfiguration());
}
+
+ @Test
+ public void testFixedRotationAdjustments() {
+ final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+ final int realRotation = Surface.ROTATION_0;
+ final int fixedRotation = Surface.ROTATION_90;
+
+ mDisplayAdjustments.setFixedRotationAdjustments(
+ new FixedRotationAdjustments(fixedRotation, null /* cutout */));
+
+ final int w = 1000;
+ final int h = 2000;
+ final Point size = new Point(w, h);
+ mDisplayAdjustments.adjustSize(size, realRotation);
+
+ assertEquals(fixedRotation, mDisplayAdjustments.getRotation(realRotation));
+ assertEquals(new Point(h, w), size);
+
+ final DisplayMetrics metrics = new DisplayMetrics();
+ metrics.xdpi = metrics.noncompatXdpi = w;
+ metrics.widthPixels = metrics.noncompatWidthPixels = w;
+ metrics.ydpi = metrics.noncompatYdpi = h;
+ metrics.heightPixels = metrics.noncompatHeightPixels = h;
+
+ final DisplayMetrics flippedMetrics = new DisplayMetrics();
+ flippedMetrics.xdpi = flippedMetrics.noncompatXdpi = h;
+ flippedMetrics.widthPixels = flippedMetrics.noncompatWidthPixels = h;
+ flippedMetrics.ydpi = flippedMetrics.noncompatYdpi = w;
+ flippedMetrics.heightPixels = flippedMetrics.noncompatHeightPixels = w;
+
+ mDisplayAdjustments.adjustMetrics(metrics, realRotation);
+
+ assertEquals(flippedMetrics, metrics);
+ }
}
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 0390ac6b8e9c..1cdc75aa1f40 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -225,7 +225,8 @@ public class ActivityThreadClientTest {
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null /* referrer */,
null /* voiceInteractor */, null /* state */, null /* persistentState */,
null /* pendingResults */, null /* pendingNewIntents */, true /* isForward */,
- null /* profilerInfo */, mThread /* client */, null /* asssitToken */);
+ null /* profilerInfo */, mThread /* client */, null /* asssitToken */,
+ null /* fixedRotationAdjustments */);
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index fb7ba62b5fd2..afd92c74eda3 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -842,7 +842,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
- r.assistToken));
+ r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index cf585df87f24..768f89eff774 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.os.Process.INVALID_UID;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -40,6 +41,7 @@ import static com.android.server.wm.WindowTokenProto.WINDOW_CONTAINER;
import android.annotation.CallSuper;
import android.app.IWindowToken;
+import android.app.servertransaction.FixedRotationAdjustmentsItem;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Debug;
@@ -47,6 +49,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import android.view.DisplayAdjustments.FixedRotationAdjustments;
import android.view.DisplayInfo;
import android.view.InsetsState;
import android.view.SurfaceControl;
@@ -529,6 +532,7 @@ class WindowToken extends WindowContainer<WindowState> {
mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames,
insetsState, new Configuration(config), mDisplayContent.getRotation());
onConfigurationChanged(getParent().getConfiguration());
+ notifyFixedRotationTransform(true /* enabled */);
}
/**
@@ -546,6 +550,7 @@ class WindowToken extends WindowContainer<WindowState> {
mFixedRotationTransformState = fixedRotationState;
fixedRotationState.mAssociatedTokens.add(this);
onConfigurationChanged(getParent().getConfiguration());
+ notifyFixedRotationTransform(true /* enabled */);
}
void finishFixedRotationTransform() {
@@ -578,9 +583,52 @@ class WindowToken extends WindowContainer<WindowState> {
// The state is cleared at the end, because it is used to indicate that other windows can
// use seamless rotation when applying rotation to display.
for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
- state.mAssociatedTokens.get(i).mFixedRotationTransformState = null;
+ state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState();
}
+ cleanUpFixedRotationTransformState();
+ }
+
+ private void cleanUpFixedRotationTransformState() {
mFixedRotationTransformState = null;
+ notifyFixedRotationTransform(false /* enabled */);
+ }
+
+ /** Notifies application side to enable or disable the rotation adjustment of display info. */
+ private void notifyFixedRotationTransform(boolean enabled) {
+ FixedRotationAdjustments adjustments = null;
+ // A token may contain windows of the same processes or different processes. The list is
+ // used to avoid sending the same adjustments to a process multiple times.
+ ArrayList<WindowProcessController> notifiedProcesses = null;
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = mChildren.get(i);
+ final WindowProcessController app;
+ if (w.mAttrs.type == TYPE_APPLICATION_STARTING) {
+ // Use the host activity because starting window is controlled by window manager.
+ final ActivityRecord r = asActivityRecord();
+ if (r == null) {
+ continue;
+ }
+ app = r.app;
+ } else {
+ app = mWmService.mAtmService.mProcessMap.getProcess(w.mSession.mPid);
+ }
+ if (app == null || !app.hasThread()) {
+ continue;
+ }
+ if (notifiedProcesses == null) {
+ notifiedProcesses = new ArrayList<>(2);
+ adjustments = enabled ? createFixedRotationAdjustmentsIfNeeded() : null;
+ } else if (notifiedProcesses.contains(app)) {
+ continue;
+ }
+ notifiedProcesses.add(app);
+ try {
+ mWmService.mAtmService.getLifecycleManager().scheduleTransaction(
+ app.getThread(), FixedRotationAdjustmentsItem.obtain(token, adjustments));
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to schedule DisplayAdjustmentsItem to " + app, e);
+ }
+ }
}
/** Restores the changes that applies to this container. */
@@ -590,6 +638,7 @@ class WindowToken extends WindowContainer<WindowState> {
// The window may be detached or detaching.
return;
}
+ notifyFixedRotationTransform(false /* enabled */);
final int originalRotation = getWindowConfiguration().getRotation();
onConfigurationChanged(parent.getConfiguration());
onCancelFixedRotationTransform(originalRotation);
@@ -603,6 +652,14 @@ class WindowToken extends WindowContainer<WindowState> {
void onCancelFixedRotationTransform(int originalDisplayRotation) {
}
+ FixedRotationAdjustments createFixedRotationAdjustmentsIfNeeded() {
+ if (!isFixedRotationTransforming()) {
+ return null;
+ }
+ return new FixedRotationAdjustments(mFixedRotationTransformState.mDisplayInfo.rotation,
+ mFixedRotationTransformState.mDisplayInfo.displayCutout);
+ }
+
@Override
void resolveOverrideConfiguration(Configuration newParentConfig) {
super.resolveOverrideConfiguration(newParentConfig);