diff options
| 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 |
| commit | 8e726a2ef72965430f514b0d8fa17a01798e51dc (patch) | |
| tree | 89e98a59b3571079dbe40836edc46d59f0eea904 /core/java | |
| parent | 80dcec801deb24186ce375da85c5b96bc2437038 (diff) | |
| parent | d490c57905bc47a4d583d69049864e6348171c61 (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
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/Activity.java | 5 | ||||
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 60 | ||||
| -rw-r--r-- | core/java/android/app/ClientTransactionHandler.java | 5 | ||||
| -rw-r--r-- | core/java/android/app/ResourcesManager.java | 30 | ||||
| -rw-r--r-- | core/java/android/app/servertransaction/FixedRotationAdjustmentsItem.java | 112 | ||||
| -rw-r--r-- | core/java/android/app/servertransaction/LaunchActivityItem.java | 24 | ||||
| -rw-r--r-- | core/java/android/content/res/Resources.java | 35 | ||||
| -rw-r--r-- | core/java/android/view/Display.java | 32 | ||||
| -rw-r--r-- | core/java/android/view/DisplayAdjustments.java | 152 |
9 files changed, 440 insertions, 15 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]; + } + }; } } |
