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

Commit 441e1a93 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/29010743',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/29010743', 'googleplex-android-review.googlesource.com/29031227'] into 24Q4-release.

Change-Id: Ieb5dfc0839b3e5a88d93860ea40130f2a06d1c36
parents a0930b79 c9bff6bb
Loading
Loading
Loading
Loading
+62 −55
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.internal.protolog;

import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.DEFAULT;
import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.DEFAULT_LOG_FROM_LEVEL;
import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.ENABLE_ALL;
import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.GROUP_OVERRIDES;
import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.TRACING_MODE;
@@ -44,6 +43,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
        ProtoLogDataSource.TlsState,
@@ -190,15 +190,7 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
        final Map<String, GroupConfig> groupConfigs = new HashMap<>();

        while (configStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
            switch (configStream.getFieldNumber()) {
                case (int) DEFAULT_LOG_FROM_LEVEL:
                    int defaultLogFromLevelInt = configStream.readInt(DEFAULT_LOG_FROM_LEVEL);
                    if (defaultLogFromLevelInt < defaultLogFromLevel.ordinal()) {
                        defaultLogFromLevel =
                                logLevelFromInt(configStream.readInt(DEFAULT_LOG_FROM_LEVEL));
                    }
                    break;
                case (int) TRACING_MODE:
            if (configStream.getFieldNumber() == (int) TRACING_MODE) {
                int tracingMode = configStream.readInt(TRACING_MODE);
                switch (tracingMode) {
                    case DEFAULT:
@@ -209,8 +201,8 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
                    default:
                        throw new RuntimeException("Unhandled ProtoLog tracing mode type");
                }
                    break;
                case (int) GROUP_OVERRIDES:
            }
            if (configStream.getFieldNumber() == (int) GROUP_OVERRIDES) {
                final long group_overrides_token  = configStream.start(GROUP_OVERRIDES);

                String tag = null;
@@ -222,7 +214,35 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
                    }
                    if (configStream.getFieldNumber() == (int) LOG_FROM) {
                        final int logFromInt = configStream.readInt(LOG_FROM);
                            logFromLevel = logLevelFromInt(logFromInt);
                        switch (logFromInt) {
                            case (ProtologCommon.PROTOLOG_LEVEL_DEBUG): {
                                logFromLevel = LogLevel.DEBUG;
                                break;
                            }
                            case (ProtologCommon.PROTOLOG_LEVEL_VERBOSE): {
                                logFromLevel = LogLevel.VERBOSE;
                                break;
                            }
                            case (ProtologCommon.PROTOLOG_LEVEL_INFO): {
                                logFromLevel = LogLevel.INFO;
                                break;
                            }
                            case (ProtologCommon.PROTOLOG_LEVEL_WARN): {
                                logFromLevel = LogLevel.WARN;
                                break;
                            }
                            case (ProtologCommon.PROTOLOG_LEVEL_ERROR): {
                                logFromLevel = LogLevel.ERROR;
                                break;
                            }
                            case (ProtologCommon.PROTOLOG_LEVEL_WTF): {
                                logFromLevel = LogLevel.WTF;
                                break;
                            }
                            default: {
                                throw new RuntimeException("Unhandled log level");
                            }
                        }
                    }
                    if (configStream.getFieldNumber() == (int) COLLECT_STACKTRACE) {
                        collectStackTrace = configStream.readBoolean(COLLECT_STACKTRACE);
@@ -237,7 +257,6 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
                groupConfigs.put(tag, new GroupConfig(logFromLevel, collectStackTrace));

                configStream.end(group_overrides_token);
                    break;
            }
        }

@@ -246,18 +265,6 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
        return new ProtoLogConfig(defaultLogFromLevel, groupConfigs);
    }

    private LogLevel logLevelFromInt(int logFromInt) {
        return switch (logFromInt) {
            case (ProtologCommon.PROTOLOG_LEVEL_DEBUG) -> LogLevel.DEBUG;
            case (ProtologCommon.PROTOLOG_LEVEL_VERBOSE) -> LogLevel.VERBOSE;
            case (ProtologCommon.PROTOLOG_LEVEL_INFO) -> LogLevel.INFO;
            case (ProtologCommon.PROTOLOG_LEVEL_WARN) -> LogLevel.WARN;
            case (ProtologCommon.PROTOLOG_LEVEL_ERROR) -> LogLevel.ERROR;
            case (ProtologCommon.PROTOLOG_LEVEL_WTF) -> LogLevel.WTF;
            default -> throw new RuntimeException("Unhandled log level");
        };
    }

    public static class Instance extends DataSourceInstance {

        public interface TracingInstanceStartCallback {
+0 −239
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 com.android.server.wm;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Slog;

import com.android.window.flags.Flags;

/**
 * Represents a chain of WM actions where each action is "caused by" the prior action (except the
 * first one of course). A whole chain is associated with one Transition (in fact, the purpose
 * of this object is to communicate, to all callees, which transition they are part of).
 *
 * A single action is defined as "one logical thing requested of WM". This usually corresponds to
 * each ingress-point into the process. For example, when starting an activity:
 *   * the first action is to pause the current/top activity.
 *       At this point, control leaves the process while the activity pauses.
 *   * Then WM receives completePause (a new ingress). This is a new action that gets linked
 *       to the prior action. This action involves resuming the next activity, at which point,
 *       control leaves the process again.
 *   * Eventually, when everything is done, we will have formed a chain of actions.
 *
 * We don't technically need to hold onto each prior action in the chain once a new action has
 * been linked to the same transition; however, keeping the whole chain enables improved
 * debugging and the ability to detect anomalies.
 */
public class ActionChain {
    private static final String TAG = "TransitionChain";

    /**
     * Normal link type. This means the action was expected and is properly linked to the
     * current chain.
     */
    static final int TYPE_NORMAL = 0;

    /**
     * This is the "default" link. It means we haven't done anything to properly track this case
     * so it may or may not be correct. It represents the behavior as if there was no tracking.
     *
     * Any type that has "default" behavior uses the global "collecting transition" if it exists,
     * otherwise it doesn't use any transition.
     */
    static final int TYPE_DEFAULT = 1;

    /**
     * This means the action was performed via a legacy code-path. These should be removed
     * eventually. This will have the "default" behavior.
     */
    static final int TYPE_LEGACY = 2;

    /** This is for a test. */
    static final int TYPE_TEST = 3;

    /** This is finishing a transition. Collection isn't supported during this. */
    static final int TYPE_FINISH = 4;

    /**
     * Something unexpected happened so this action was started to recover from the unexpected
     * state. This means that a "real" chain-link couldn't be determined. For now, the behavior of
     * this is the same as "default".
     */
    static final int TYPE_FAILSAFE = 5;

    /**
     * Types of chain links (ie. how is this action associated with the chain it is linked to).
     * @hide
     */
    @IntDef(prefix = { "TYPE_" }, value = {
            TYPE_NORMAL,
            TYPE_DEFAULT,
            TYPE_LEGACY,
            TYPE_TEST,
            TYPE_FINISH,
            TYPE_FAILSAFE
    })
    public @interface LinkType {}

    /** Identifies the entry-point of this action. */
    @NonNull
    final String mSource;

    /** Reference to ATMS. TEMPORARY! ONLY USE THIS WHEN tracker_plumbing flag is DISABLED! */
    @Nullable
    ActivityTaskManagerService mTmpAtm;

    /** The transition that this chain's changes belong to. */
    @Nullable
    Transition mTransition;

    /** The previous action in the chain. */
    @Nullable
    ActionChain mPrevious = null;

    /** Classification of how this action is connected to the chain. */
    @LinkType int mType = TYPE_NORMAL;

    /** When this Action started. */
    long mCreateTimeMs;

    private ActionChain(String source, @LinkType int type, Transition transit) {
        mSource = source;
        mCreateTimeMs = System.currentTimeMillis();
        mType = type;
        mTransition = transit;
        if (mTransition != null) {
            mTransition.recordChain(this);
        }
    }

    private Transition getTransition() {
        if (!Flags.transitTrackerPlumbing()) {
            return mTmpAtm.getTransitionController().getCollectingTransition();
        }
        return mTransition;
    }

    boolean isFinishing() {
        return mType == TYPE_FINISH;
    }

    /**
     * Some common checks to determine (and report) whether this chain has a collecting transition.
     */
    private boolean expectCollecting() {
        if (getTransition() == null) {
            Slog.e(TAG, "Can't collect into a chain with no transition");
            return false;
        }
        if (isFinishing()) {
            Slog.e(TAG, "Trying to collect into a finished transition");
            return false;
        }
        if (mTransition.mController.getCollectingTransition() != mTransition) {
            Slog.e(TAG, "Mismatch between current collecting ("
                    + mTransition.mController.getCollectingTransition() + ") and chain ("
                    + mTransition + ")");
            return false;
        }
        return true;
    }

    /**
     * Helper to collect a container into the associated transition. This will automatically do
     * nothing if the chain isn't associated with a collecting transition.
     */
    void collect(@NonNull WindowContainer wc) {
        if (!wc.mTransitionController.isShellTransitionsEnabled()) return;
        if (!expectCollecting()) return;
        getTransition().collect(wc);
    }

    /**
     * An interface for creating and tracking action chains.
     */
    static class Tracker {
        private final ActivityTaskManagerService mAtm;

        Tracker(ActivityTaskManagerService atm) {
            mAtm = atm;
        }

        private ActionChain makeChain(String source, @LinkType int type, Transition transit) {
            final ActionChain out = new ActionChain(source, type, transit);
            if (!Flags.transitTrackerPlumbing()) {
                out.mTmpAtm = mAtm;
            }
            return out;
        }

        private ActionChain makeChain(String source, @LinkType int type) {
            return makeChain(source, type,
                    mAtm.getTransitionController().getCollectingTransition());
        }

        /**
         * Starts tracking a normal action.
         * @see #TYPE_NORMAL
         */
        @NonNull
        ActionChain start(String source, Transition transit) {
            return makeChain(source, TYPE_NORMAL, transit);
        }

        /** @see #TYPE_DEFAULT */
        @NonNull
        ActionChain startDefault(String source) {
            return makeChain(source, TYPE_DEFAULT);
        }

        /**
         * Starts tracking an action that finishes a transition.
         * @see #TYPE_NORMAL
         */
        @NonNull
        ActionChain startFinish(String source, Transition finishTransit) {
            return makeChain(source, TYPE_FINISH, finishTransit);
        }

        /** @see #TYPE_LEGACY */
        @NonNull
        ActionChain startLegacy(String source) {
            return makeChain(source, TYPE_LEGACY, null);
        }

        /** @see #TYPE_FAILSAFE */
        @NonNull
        ActionChain startFailsafe(String source) {
            return makeChain(source, TYPE_FAILSAFE);
        }
    }

    /** Helpers for usage in tests. */
    @NonNull
    static ActionChain test() {
        return new ActionChain("test", TYPE_TEST, null /* transition */);
    }

    @NonNull
    static ActionChain testFinish(Transition toFinish) {
        return new ActionChain("test", TYPE_FINISH, toFinish);
    }
}
+0 −2
Original line number Diff line number Diff line
@@ -795,7 +795,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    WindowOrganizerController mWindowOrganizerController;
    TaskOrganizerController mTaskOrganizerController;
    TaskFragmentOrganizerController mTaskFragmentOrganizerController;
    ActionChain.Tracker mChainTracker;

    @Nullable
    private BackgroundActivityStartCallback mBackgroundActivityStartCallback;
@@ -870,7 +869,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        mInternal = new LocalService();
        GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED);
        mWindowOrganizerController = new WindowOrganizerController(this);
        mChainTracker = new ActionChain.Tracker(this);
        mTaskOrganizerController = mWindowOrganizerController.mTaskOrganizerController;
        mTaskFragmentOrganizerController =
                mWindowOrganizerController.mTaskFragmentOrganizerController;
+3 −15
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
    final @TransitionType int mType;
    private int mSyncId = -1;
    private @TransitionFlags int mFlags;
    final TransitionController mController;
    private final TransitionController mController;
    private final BLASTSyncEngine mSyncEngine;
    private final Token mToken;

@@ -329,9 +329,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
     */
    ArrayList<ActivityRecord> mConfigAtEndActivities = null;

    /** The current head of the chain of actions related to this transition. */
    ActionChain mChainHead = null;

    @VisibleForTesting
    Transition(@TransitionType int type, @TransitionFlags int flags,
            TransitionController controller, BLASTSyncEngine syncEngine) {
@@ -1210,14 +1207,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
     * The transition has finished animating and is ready to finalize WM state. This should not
     * be called directly; use {@link TransitionController#finishTransition} instead.
     */
    void finishTransition(@NonNull ActionChain chain) {
    void finishTransition() {
        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER) && mIsPlayerEnabled) {
            asyncTraceEnd(System.identityHashCode(this));
        }
        if (!chain.isFinishing()) {
            throw new IllegalStateException("Can't finish on a non-finishing transition "
                    + chain.mTransition);
        }
        mLogger.mFinishTimeNs = SystemClock.elapsedRealtimeNanos();
        mController.mLoggerHandler.post(mLogger::logOnFinish);
        mController.mTransitionTracer.logFinishedTransition(this);
@@ -2170,7 +2163,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        if (mFinishTransaction != null) {
            mFinishTransaction.apply();
        }
        mController.finishTransition(mController.mAtm.mChainTracker.startFinish("clean-up", this));
        mController.finishTransition(this);
    }

    private void cleanUpInternal() {
@@ -3386,11 +3379,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        return false;
    }

    void recordChain(@NonNull ActionChain chain) {
        chain.mPrevious = mChainHead;
        mChainHead = chain;
    }

    @VisibleForTesting
    static class ChangeInfo {
        private static final int FLAG_NONE = 0;
+3 −8
Original line number Diff line number Diff line
@@ -52,8 +52,8 @@ import android.window.WindowContainerTransaction;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.ProtoLog;
import com.android.server.FgThread;
import com.android.window.flags.Flags;

@@ -921,12 +921,7 @@ class TransitionController {
    }

    /** @see Transition#finishTransition */
    void finishTransition(@NonNull ActionChain chain) {
        if (!chain.isFinishing()) {
            throw new IllegalStateException("Can't finish on a non-finishing transition "
                    + chain.mTransition);
        }
        final Transition record = chain.mTransition;
    void finishTransition(Transition record) {
        // It is usually a no-op but make sure that the metric consumer is removed.
        mTransitionMetricsReporter.reportAnimationStart(record.getToken(), 0 /* startTime */);
        // It is a no-op if the transition did not change the display.
@@ -942,7 +937,7 @@ class TransitionController {
            mTrackCount = 0;
        }
        updateRunningRemoteAnimation(record, false /* isPlaying */);
        record.finishTransition(chain);
        record.finishTransition();
        for (int i = mAnimatingExitWindows.size() - 1; i >= 0; i--) {
            final WindowState w = mAnimatingExitWindows.get(i);
            if (w.mAnimatingExit && w.mHasSurface && !w.inTransition()) {
Loading