Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d490c579 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Send fixed rotation adjustments to the associated client

So the real information of display can be adjusted according
to the adjustments for the application started with fixed
rotation transform.

The enabling adjustments may be sent in different ways:
- Launch activity
  The information is bundled with LaunchActivityItem.
- Resume activity or update non-activity window
  Send a standalone FixedRotationAdjustmentsItem.

The disabling adjustments (null) are always sent by
FixedRotationAdjustmentsItem.

Bug: 147213487
Test: AppConfigurationTests#testRotatedInfoWithFixedRotationTransform
      TransactionParcelTests#testFixedRotationAdjustments

Change-Id: I5238888a5c8352db83fc12749f4de2bfabf46026
parent e03b9669
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -7150,6 +7150,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);
+59 −1
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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.
+112 −0
Original line number Diff line number Diff line
/*
 * 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];
        }
    };
}
+16 −8
Original line number Diff line number Diff line
@@ -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;
    }
}
Loading